mirror of https://github.com/MidnightCommander/mc
Merge branch '1585_slow_viewer'
* 1585_slow_viewer: added new parameter mcview_eof into ini-file added procedure mcview_update_filesize, Optimization of viewer screen content update. Fixed left/right movement in hex mode Fixed viewer button bar. New 'Goto' dialog implementation in viewer. Little refactoring of load_file_position, save_file_position (added new param 'offset') Fixed drawing of viewer status bar. this commit make the viewer faster. First step of viewer coordinates cache reimplementation. Ticket #1585: mc viwer is slow.
This commit is contained in:
commit
4c6b5fc569
14
edit/edit.c
14
edit/edit.c
|
@ -689,16 +689,22 @@ edit_load_position (WEdit *edit)
|
|||
{
|
||||
char *filename;
|
||||
long line, column;
|
||||
off_t offset;
|
||||
|
||||
if (!edit->filename || !*edit->filename)
|
||||
return;
|
||||
|
||||
filename = vfs_canon (edit->filename);
|
||||
load_file_position (filename, &line, &column);
|
||||
load_file_position (filename, &line, &column, &offset);
|
||||
g_free (filename);
|
||||
|
||||
edit_move_to_line (edit, line - 1);
|
||||
edit->prev_col = column;
|
||||
if (line > 0) {
|
||||
edit_move_to_line (edit, line - 1);
|
||||
edit->prev_col = column;
|
||||
} else if (offset > 0) {
|
||||
edit_cursor_move (edit, offset);
|
||||
line = edit->curs_line;
|
||||
}
|
||||
edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1));
|
||||
edit_move_display (edit, line - (edit->num_widget_lines / 2));
|
||||
}
|
||||
|
@ -713,7 +719,7 @@ edit_save_position (WEdit *edit)
|
|||
return;
|
||||
|
||||
filename = vfs_canon (edit->filename);
|
||||
save_file_position (filename, edit->curs_line + 1, edit->curs_col);
|
||||
save_file_position (filename, edit->curs_line + 1, edit->curs_col, edit->curs1);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define MC_HISTORY_FM_PANEL_FILTER "mc.fm.panel-filter"
|
||||
#define MC_HISTORY_FM_MENU_EXEC_PARAM "mc.fm.menu.exec.parameter"
|
||||
|
||||
#define MC_HISTORY_VIEW_GOTO "mc.view.goto"
|
||||
#define MC_HISTORY_VIEW_GOTO_LINE "mc.view.goto-line"
|
||||
#define MC_HISTORY_VIEW_GOTO_ADDR "mc.view.goto-addr"
|
||||
#define MC_HISTORY_VIEW_SEARCH_REGEX "mc.view.search.regex"
|
||||
|
|
|
@ -241,6 +241,7 @@ static const struct {
|
|||
#ifdef USE_INTERNAL_EDIT
|
||||
{ "editor_backup_extension", &option_backup_ext, "~" },
|
||||
#endif
|
||||
{ "mcview_eof", &mcview_show_eof, "" },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
32
src/util.c
32
src/util.c
|
@ -1349,7 +1349,7 @@ mc_mkstemps (char **pname, const char *prefix, const char *suffix)
|
|||
* If there is no stored data, return line 1 and col 0.
|
||||
*/
|
||||
void
|
||||
load_file_position (const char *filename, long *line, long *column)
|
||||
load_file_position (const char *filename, long *line, long *column, off_t *offset)
|
||||
{
|
||||
char *fn;
|
||||
FILE *f;
|
||||
|
@ -1359,6 +1359,7 @@ load_file_position (const char *filename, long *line, long *column)
|
|||
/* defaults */
|
||||
*line = 1;
|
||||
*column = 0;
|
||||
*offset = 0;
|
||||
|
||||
/* open file with positions */
|
||||
fn = g_build_filename (home_dir, MC_USERCONF_DIR, MC_FILEPOS_FILE, NULL);
|
||||
|
@ -1371,6 +1372,7 @@ load_file_position (const char *filename, long *line, long *column)
|
|||
|
||||
while (fgets (buf, sizeof (buf), f)) {
|
||||
const char *p;
|
||||
gchar **pos_tokens;
|
||||
|
||||
/* check if the filename matches the beginning of string */
|
||||
if (strncmp (buf, filename, len) != 0)
|
||||
|
@ -1385,13 +1387,25 @@ load_file_position (const char *filename, long *line, long *column)
|
|||
if (strchr (p, ' '))
|
||||
continue;
|
||||
|
||||
*line = strtol(p, const_cast(char **, &p), 10);
|
||||
if (*p == ';') {
|
||||
*column = strtol(p+1, const_cast(char **, &p), 10);
|
||||
if (*p != '\n')
|
||||
*column = 0;
|
||||
} else
|
||||
pos_tokens = g_strsplit_set (p, ";", 3);
|
||||
if (pos_tokens[0] != NULL) {
|
||||
*line = strtol (pos_tokens[0], NULL, 10);
|
||||
if (pos_tokens[1] != NULL) {
|
||||
*column = strtol (pos_tokens[1], NULL, 10);
|
||||
if (pos_tokens[2] != NULL)
|
||||
*offset = strtoll (pos_tokens[2], NULL, 10);
|
||||
else
|
||||
*offset = 0;
|
||||
} else {
|
||||
*column = 0;
|
||||
*offset = 0;
|
||||
}
|
||||
} else {
|
||||
*line = 1;
|
||||
*column = 0;
|
||||
*offset = 0;
|
||||
}
|
||||
g_strfreev(pos_tokens);
|
||||
}
|
||||
fclose (f);
|
||||
}
|
||||
|
@ -1399,7 +1413,7 @@ load_file_position (const char *filename, long *line, long *column)
|
|||
/* Save position for the given file */
|
||||
#define TMP_SUFFIX ".tmp"
|
||||
void
|
||||
save_file_position (const char *filename, long line, long column)
|
||||
save_file_position (const char *filename, long line, long column, off_t offset)
|
||||
{
|
||||
static int filepos_max_saved_entries = 0;
|
||||
char *fn, *tmp_fn;
|
||||
|
@ -1431,7 +1445,7 @@ save_file_position (const char *filename, long line, long column)
|
|||
|
||||
/* put the new record */
|
||||
if (line != 1 || column != 0) {
|
||||
if (fprintf (f, "%s %ld;%ld\n", filename, line, column) < 0)
|
||||
if (fprintf (f, "%s %ld;%ld;%lli\n", filename, line, column, offset) < 0)
|
||||
goto write_position_error;
|
||||
}
|
||||
|
||||
|
|
|
@ -222,9 +222,9 @@ GList *list_append_unique (GList *list, char *text);
|
|||
/* Position saving and restoring */
|
||||
|
||||
/* Load position for the given filename */
|
||||
void load_file_position (const char *filename, long *line, long *column);
|
||||
void load_file_position (const char *filename, long *line, long *column, off_t *offset);
|
||||
/* Save position for the given filename */
|
||||
void save_file_position (const char *filename, long line, long column);
|
||||
void save_file_position (const char *filename, long line, long column, off_t offset);
|
||||
|
||||
|
||||
/* OS specific defines */
|
||||
|
|
|
@ -206,50 +206,6 @@ mcview_cmk_moveto_bottom (void *w, int n)
|
|||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static inline void
|
||||
mcview_moveto_line_cmd (mcview_t *view)
|
||||
{
|
||||
char *answer, *answer_end, prompt[BUF_SMALL];
|
||||
off_t line, col;
|
||||
|
||||
mcview_offset_to_coord (view, &line, &col, view->dpy_start);
|
||||
|
||||
g_snprintf (prompt, sizeof (prompt),
|
||||
_(" The current line number is %lld.\n"
|
||||
" Enter the new line number:"), (long long)(line + 1));
|
||||
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 (errno == 0 && *answer_end == '\0' && line >= 1)
|
||||
mcview_moveto (view, line - 1, 0);
|
||||
}
|
||||
g_free (answer);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mcview_moveto_addr_cmd (mcview_t *view)
|
||||
{
|
||||
char *line, *error, prompt[BUF_SMALL], prompt_format[BUF_SMALL];
|
||||
|
||||
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);
|
||||
line = input_dialog (_(" Goto Address "), prompt, MC_HISTORY_VIEW_GOTO_ADDR, "");
|
||||
if ((line != NULL) && (*line != '\0')) {
|
||||
off_t addr;
|
||||
addr = strtoul (line, &error, 0);
|
||||
if ((*error == '\0') && mcview_get_byte (view, addr, NULL))
|
||||
mcview_moveto_offset (view, addr);
|
||||
else
|
||||
message (D_ERROR, _("Warning"), _(" Invalid address "));
|
||||
}
|
||||
g_free (line);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_hook (void *v)
|
||||
{
|
||||
|
@ -327,7 +283,6 @@ mcview_handle_editkey (mcview_t * view, int key)
|
|||
node->value = byte_val;
|
||||
}
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
mcview_move_right (view, 1);
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
@ -346,26 +301,32 @@ mcview_execute_cmd (mcview_t *view, unsigned long command)
|
|||
case CK_ViewToggleWrapMode:
|
||||
/* Toggle between wrapped and unwrapped view */
|
||||
mcview_toggle_wrap_mode (view);
|
||||
mcview_update (view); /* FIXME: view->dirty++ ? */
|
||||
view->dirty++;
|
||||
break;
|
||||
case CK_ViewToggleHexEditMode:
|
||||
/* Toggle between hexview and hexedit mode */
|
||||
mcview_toggle_hexedit_mode (view);
|
||||
mcview_update (view); /* FIXME: view->dirty++ ? */
|
||||
view->dirty++;
|
||||
break;
|
||||
case CK_ViewToggleHexMode:
|
||||
/* Toggle between hex view and text view */
|
||||
mcview_toggle_hex_mode (view);
|
||||
mcview_update (view); /* FIXME: view->dirty++ ? */
|
||||
view->dirty++;
|
||||
break;
|
||||
case CK_ViewGoto:
|
||||
if (view->hex_mode)
|
||||
mcview_moveto_addr_cmd (view);
|
||||
else
|
||||
mcview_moveto_line_cmd (view);
|
||||
view->dirty++;
|
||||
mcview_update (view); /* FIXME: unneeded? */
|
||||
{
|
||||
off_t addr;
|
||||
|
||||
if (mcview_dialog_goto (view, &addr)) {
|
||||
if (addr >= 0)
|
||||
mcview_moveto_offset (view, addr);
|
||||
else {
|
||||
message (D_ERROR, _("Warning"), _("Invalid value"));
|
||||
view->dirty++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CK_ViewHexEditSave:
|
||||
mcview_hexedit_save_changes (view);
|
||||
break;
|
||||
|
@ -374,11 +335,11 @@ mcview_execute_cmd (mcview_t *view, unsigned long command)
|
|||
break;
|
||||
case CK_ViewToggleMagicMode:
|
||||
mcview_toggle_magic_mode (view);
|
||||
mcview_update (view); /* FIXME: view->dirty++ ? */
|
||||
view->dirty++;
|
||||
break;
|
||||
case CK_ViewToggleNroffMode:
|
||||
mcview_toggle_nroff_mode (view);
|
||||
mcview_update (view); /* FIXME: view->dirty++ ? */
|
||||
view->dirty++;
|
||||
break;
|
||||
case CK_ViewToggleHexNavMode:
|
||||
view->hexview_in_text = !view->hexview_in_text;
|
||||
|
@ -386,7 +347,6 @@ mcview_execute_cmd (mcview_t *view, unsigned long command)
|
|||
break;
|
||||
case CK_ViewMoveToBol:
|
||||
mcview_moveto_bol (view);
|
||||
view->dirty++;
|
||||
break;
|
||||
case CK_ViewMoveToEol:
|
||||
mcview_moveto_eol (view);
|
||||
|
@ -441,7 +401,6 @@ mcview_execute_cmd (mcview_t *view, unsigned long command)
|
|||
case CK_SelectCodepage:
|
||||
mcview_select_encoding (view);
|
||||
view->dirty++;
|
||||
mcview_update (view);
|
||||
break;
|
||||
case CK_ViewNextFile:
|
||||
case CK_ViewPrevFile:
|
||||
|
|
|
@ -51,39 +51,106 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h> /* for g_memmove() */
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/tty/tty.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define VIEW_COORD_CACHE_GRANUL 1024
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
#define VIEW_COORD_CACHE_GRANUL 1024
|
||||
#define CACHE_CAPACITY_DELTA 64
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
typedef gboolean (*cmp_func_t) (const coord_cache_entry_t *a,
|
||||
const coord_cache_entry_t *b);
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* insert new cache entry into the cache */
|
||||
static void
|
||||
mcview_ccache_add_entry (coord_cache_t *cache,
|
||||
size_t pos, const coord_cache_entry_t *entry)
|
||||
{
|
||||
if ((cache == NULL) || (entry == NULL))
|
||||
return;
|
||||
|
||||
pos = min (pos, cache->size);
|
||||
|
||||
/* increase cache capacity if needed */
|
||||
if (cache->size == cache->capacity) {
|
||||
cache->capacity += CACHE_CAPACITY_DELTA;
|
||||
cache->cache = g_realloc (cache->cache,
|
||||
cache->capacity * sizeof (coord_cache_entry_t *));
|
||||
}
|
||||
|
||||
/* insert new entry */
|
||||
if (pos != cache->size)
|
||||
g_memmove (cache->cache[pos + 1], cache->cache[pos],
|
||||
(cache->size - pos) * sizeof (coord_cache_entry_t *));
|
||||
cache->cache[pos] = g_memdup (entry, sizeof (coord_cache_entry_t));
|
||||
cache->size++;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mcview_coord_cache_entry_less_offset (const coord_cache_entry_t *a,
|
||||
const coord_cache_entry_t *b)
|
||||
{
|
||||
return (a->cc_offset < b->cc_offset);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mcview_coord_cache_entry_less_plain (const coord_cache_entry_t *a,
|
||||
const coord_cache_entry_t *b)
|
||||
{
|
||||
if (a->cc_line < b->cc_line)
|
||||
return TRUE;
|
||||
|
||||
if (a->cc_line == b->cc_line)
|
||||
return (a->cc_column < b->cc_column);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
mcview_coord_cache_entry_less_nroff (const coord_cache_entry_t *a,
|
||||
const coord_cache_entry_t *b)
|
||||
{
|
||||
if (a->cc_line < b->cc_line)
|
||||
return TRUE;
|
||||
|
||||
if (a->cc_line == b->cc_line)
|
||||
return (a->cc_nroff_column < b->cc_nroff_column);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Find and return the index of the last cache entry that is
|
||||
* smaller than ''coord'', according to the criterion ''sort_by''. */
|
||||
static guint
|
||||
mcview_ccache_find (mcview_t * view, const struct coord_cache_entry *cache,
|
||||
const struct coord_cache_entry *coord, enum ccache_type sort_by)
|
||||
static inline size_t
|
||||
mcview_ccache_find (mcview_t *view, const coord_cache_entry_t *coord,
|
||||
cmp_func_t cmp_func)
|
||||
{
|
||||
guint base, i, limit;
|
||||
size_t base = 0;
|
||||
size_t limit = view->coord_cache->size;
|
||||
|
||||
limit = view->coord_cache->len;
|
||||
assert (limit != 0);
|
||||
|
||||
base = 0;
|
||||
while (limit > 1) {
|
||||
size_t i;
|
||||
|
||||
i = base + limit / 2;
|
||||
if (mcview_coord_cache_entry_less (coord, &cache[i], sort_by, view->text_nroff_mode)) {
|
||||
if (cmp_func (coord, view->coord_cache->cache[i])) {
|
||||
/* continue the search in the lower half of the cache */
|
||||
} else {
|
||||
/* continue the search in the upper half of the cache */
|
||||
|
@ -94,32 +161,39 @@ mcview_ccache_find (mcview_t * view, const struct coord_cache_entry *cache,
|
|||
return base;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** 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)
|
||||
coord_cache_t *
|
||||
coord_cache_new (void)
|
||||
{
|
||||
if (crit == CCACHE_OFFSET)
|
||||
return (a->cc_offset < b->cc_offset);
|
||||
coord_cache_t *cache;
|
||||
|
||||
if (a->cc_line < b->cc_line)
|
||||
return TRUE;
|
||||
cache = g_new (coord_cache_t, 1);
|
||||
cache->size = 0;
|
||||
cache->capacity = CACHE_CAPACITY_DELTA;
|
||||
cache->cache = g_malloc0 (cache->capacity * sizeof (coord_cache_entry_t *));
|
||||
|
||||
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 cache;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
coord_cache_free (coord_cache_t *cache)
|
||||
{
|
||||
if (cache != NULL) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cache->size; i++)
|
||||
g_free (cache->cache[i]);
|
||||
|
||||
g_free (cache->cache);
|
||||
g_free (cache);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -132,12 +206,11 @@ mcview_ccache_dump (mcview_t * view)
|
|||
FILE *f;
|
||||
off_t offset, line, column, nextline_offset, filesize;
|
||||
guint i;
|
||||
const struct coord_cache_entry *cache;
|
||||
const coord_cache_t *cache = view->coord_cache;
|
||||
|
||||
assert (view->coord_cache != NULL);
|
||||
assert (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)
|
||||
|
@ -145,15 +218,15 @@ mcview_ccache_dump (mcview_t * view)
|
|||
(void) setvbuf (f, NULL, _IONBF, 0);
|
||||
|
||||
/* cache entries */
|
||||
for (i = 0; i < view->coord_cache->len; i++) {
|
||||
for (i = 0; i < view->coord_cache->size; 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);
|
||||
(unsigned int) i, cache->cache[i].cc_offset, cache[i]->cache.cc_line,
|
||||
cache->cache[i].cc_column, cache->cache[i].cc_nroff_column);
|
||||
}
|
||||
(void) fprintf (f, "\n");
|
||||
|
||||
|
@ -197,41 +270,55 @@ mcview_ccache_dump (mcview_t * view)
|
|||
* matches the existing components of ''coord''.
|
||||
*/
|
||||
void
|
||||
mcview_ccache_lookup (mcview_t * view, struct coord_cache_entry *coord,
|
||||
mcview_ccache_lookup (mcview_t * view, coord_cache_entry_t *coord,
|
||||
enum ccache_type lookup_what)
|
||||
{
|
||||
guint i;
|
||||
struct coord_cache_entry *cache, current, next, entry;
|
||||
size_t i;
|
||||
coord_cache_t *cache;
|
||||
coord_cache_entry_t current, next, entry;
|
||||
enum ccache_type sorter;
|
||||
off_t limit;
|
||||
cmp_func_t cmp_func;
|
||||
|
||||
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));
|
||||
if (view->coord_cache == NULL)
|
||||
view->coord_cache = coord_cache_new ();
|
||||
|
||||
cache = view->coord_cache;
|
||||
|
||||
if (cache->size == 0) {
|
||||
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);
|
||||
mcview_ccache_add_entry (cache, 0, ¤t);
|
||||
}
|
||||
|
||||
sorter = (lookup_what == CCACHE_OFFSET) ? CCACHE_LINECOL : CCACHE_OFFSET;
|
||||
|
||||
if (sorter == CCACHE_OFFSET)
|
||||
cmp_func = mcview_coord_cache_entry_less_offset;
|
||||
else if (view->text_nroff_mode)
|
||||
cmp_func = mcview_coord_cache_entry_less_nroff;
|
||||
else
|
||||
cmp_func = mcview_coord_cache_entry_less_plain;
|
||||
|
||||
|
||||
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);
|
||||
i = mcview_ccache_find (view, coord, cmp_func);
|
||||
/* 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;
|
||||
current = *cache->cache[i];
|
||||
if (i + 1 < view->coord_cache->size)
|
||||
limit = cache->cache[i + 1]->cc_offset;
|
||||
else
|
||||
limit = current.cc_offset + VIEW_COORD_CACHE_GRANUL;
|
||||
|
||||
|
@ -243,8 +330,9 @@ mcview_ccache_lookup (mcview_t * view, struct coord_cache_entry *coord,
|
|||
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) {
|
||||
if (!cmp_func (¤t, coord)) {
|
||||
if (lookup_what == CCACHE_OFFSET
|
||||
&& view->text_nroff_mode && nroff_state != NROFF_START) {
|
||||
/* don't break here */
|
||||
} else {
|
||||
break;
|
||||
|
@ -293,10 +381,8 @@ mcview_ccache_lookup (mcview_t * view, struct coord_cache_entry *coord,
|
|||
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;
|
||||
nroff_state = mcview_is_nroff_sequence (view, current.cc_offset)
|
||||
? NROFF_BACKSPACE : NROFF_START;
|
||||
break;
|
||||
case NROFF_BACKSPACE:
|
||||
nroff_state = NROFF_CONTINUATION;
|
||||
|
@ -311,8 +397,8 @@ mcview_ccache_lookup (mcview_t * view, struct coord_cache_entry *coord,
|
|||
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 (i + 1 == cache->size && entry.cc_offset != cache->cache[i]->cc_offset) {
|
||||
mcview_ccache_add_entry (cache, cache->size, &entry);
|
||||
|
||||
if (!tty_got_interrupt ())
|
||||
goto retry;
|
||||
|
|
|
@ -117,6 +117,18 @@ mcview_get_filesize (mcview_t * view)
|
|||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mcview_update_filesize (mcview_t * view)
|
||||
{
|
||||
if (view->datasource == DS_FILE) {
|
||||
struct stat st;
|
||||
if (mc_fstat (view->ds_file_fd, &st) != -1)
|
||||
view->ds_file_filesize = st.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
char *
|
||||
mcview_get_ptr_file (mcview_t * view, off_t byte_index)
|
||||
{
|
||||
|
|
|
@ -40,12 +40,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../src/global.h"
|
||||
|
||||
#include "../src/search/search.h"
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/wtools.h"
|
||||
#include "../src/history.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "../src/strutil.h"
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
@ -109,7 +111,7 @@ mcview_dialog_search (mcview_t * view)
|
|||
qd_result = quick_dialog (&Quick_input);
|
||||
g_strfreev (list_of_types);
|
||||
|
||||
if ((qd_result == B_CANCEL) ||(exp == NULL) || (exp[0] == '\0')) {
|
||||
if ((qd_result == B_CANCEL) || (exp == NULL) || (exp[0] == '\0')) {
|
||||
g_free (exp);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -127,28 +129,154 @@ mcview_dialog_search (mcview_t * view)
|
|||
|
||||
g_free (view->last_search_string);
|
||||
view->last_search_string = exp;
|
||||
exp = NULL;
|
||||
|
||||
if (view->search_nroff_seq)
|
||||
if (view->search_nroff_seq != NULL)
|
||||
mcview_nroff_seq_free (&(view->search_nroff_seq));
|
||||
|
||||
if (view->search)
|
||||
if (view->search != NULL)
|
||||
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);
|
||||
return FALSE;
|
||||
if (view->search != NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
return (view->search != NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mcview_dialog_goto (mcview_t *view, off_t *offset)
|
||||
{
|
||||
typedef enum {
|
||||
MC_VIEW_GOTO_LINENUM = 0,
|
||||
MC_VIEW_GOTO_PERCENT = 1,
|
||||
MC_VIEW_GOTO_OFFSET_DEC = 2,
|
||||
MC_VIEW_GOTO_OFFSET_HEX = 3
|
||||
} mcview_goto_type_t;
|
||||
|
||||
const char *mc_view_goto_str[] =
|
||||
{
|
||||
N_("&Line number (decimal)"),
|
||||
N_("Pe&rcents"),
|
||||
N_("&Decimal offset"),
|
||||
N_("He&xadecimal offset")
|
||||
};
|
||||
|
||||
const int goto_dlg_height = 12;
|
||||
int goto_dlg_width = 40;
|
||||
|
||||
static mcview_goto_type_t current_goto_type = MC_VIEW_GOTO_LINENUM;
|
||||
|
||||
size_t i;
|
||||
|
||||
size_t num_of_types = sizeof (mc_view_goto_str) /sizeof (mc_view_goto_str[0]);
|
||||
char *exp = NULL;
|
||||
int qd_result;
|
||||
gboolean res = FALSE;
|
||||
|
||||
QuickWidget quick_widgets[] =
|
||||
{
|
||||
QUICK_BUTTON (6, 10, goto_dlg_height - 3, goto_dlg_height, N_("&Cancel"), B_CANCEL, NULL),
|
||||
QUICK_BUTTON (2, 10, goto_dlg_height - 3, goto_dlg_height, N_("&OK"), B_ENTER, NULL),
|
||||
QUICK_RADIO (3, goto_dlg_width, 4, goto_dlg_height,
|
||||
num_of_types, (const char **) mc_view_goto_str, (int *) ¤t_goto_type),
|
||||
QUICK_INPUT (3, goto_dlg_width, 2, goto_dlg_height,
|
||||
INPUT_LAST_TEXT, goto_dlg_width - 6, 0, MC_HISTORY_VIEW_GOTO, &exp),
|
||||
QUICK_END
|
||||
};
|
||||
|
||||
QuickDialog Quick_input =
|
||||
{
|
||||
goto_dlg_width, goto_dlg_height, -1, -1,
|
||||
N_("Goto"), "[Input Line Keys]",
|
||||
quick_widgets, FALSE
|
||||
};
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
for (i = 0; i < num_of_types; i++)
|
||||
mc_view_goto_str [i] = _(mc_view_goto_str [i]);
|
||||
|
||||
quick_widgets[0].u.button.text = _(quick_widgets[0].u.button.text);
|
||||
quick_widgets[1].u.button.text = _(quick_widgets[1].u.button.text);
|
||||
#endif
|
||||
|
||||
/* calculate widget coordinates */
|
||||
{
|
||||
int b0_len, b1_len, len;
|
||||
const int button_gap = 2;
|
||||
|
||||
/* preliminary dialog width */
|
||||
goto_dlg_width = max (goto_dlg_width, str_term_width1 (Quick_input.title) + 4);
|
||||
|
||||
/* length of radiobuttons */
|
||||
for (i = 0; i < num_of_types; i++)
|
||||
goto_dlg_width = max (goto_dlg_width, str_term_width1 (mc_view_goto_str [i]) + 10);
|
||||
|
||||
/* length of buttons */
|
||||
b0_len = str_term_width1 (quick_widgets[0].u.button.text) + 3;
|
||||
b1_len = str_term_width1 (quick_widgets[1].u.button.text) + 5; /* default button */
|
||||
len = b0_len + b1_len + button_gap * 2;
|
||||
|
||||
/* dialog width */
|
||||
Quick_input.xlen = max (goto_dlg_width, len + 6);
|
||||
|
||||
/* correct widget coordinates */
|
||||
for (i = sizeof (quick_widgets)/sizeof (quick_widgets[0]); i > 0; i--)
|
||||
quick_widgets[i - 1].x_divisions = Quick_input.xlen;
|
||||
|
||||
/* input length */
|
||||
quick_widgets[3].u.input.len = Quick_input.xlen - 6;
|
||||
|
||||
/* button positions */
|
||||
quick_widgets[1].relative_x = Quick_input.xlen/2 - len/2;
|
||||
quick_widgets[0].relative_x = quick_widgets[1].relative_x + b1_len + button_gap;
|
||||
}
|
||||
|
||||
/* run dialog*/
|
||||
qd_result = quick_dialog (&Quick_input);
|
||||
|
||||
*offset = -1;
|
||||
|
||||
/* check input line value */
|
||||
if ((qd_result != B_CANCEL) && (exp != NULL) && (exp[0] != '\0')) {
|
||||
int base = (current_goto_type == MC_VIEW_GOTO_OFFSET_HEX) ? 16 : 10;
|
||||
off_t addr;
|
||||
char *error;
|
||||
|
||||
res = TRUE;
|
||||
|
||||
addr = strtoll (exp, &error, base);
|
||||
if ((*error == '\0') && (addr >= 0)) {
|
||||
switch (current_goto_type) {
|
||||
case MC_VIEW_GOTO_LINENUM:
|
||||
mcview_coord_to_offset (view, offset, addr, 0);
|
||||
break;
|
||||
case MC_VIEW_GOTO_PERCENT:
|
||||
if (addr > 100)
|
||||
addr = 100;
|
||||
*offset = addr * mcview_get_filesize (view) / 100;
|
||||
break;
|
||||
case MC_VIEW_GOTO_OFFSET_DEC:
|
||||
*offset = addr;
|
||||
break;
|
||||
case MC_VIEW_GOTO_OFFSET_HEX:
|
||||
*offset = addr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*offset = mcview_bol (view, *offset);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (exp);
|
||||
return TRUE;
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
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>
|
||||
2009, 2010 Ilia Maslakov <il.smind@gmail.com>
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
|
@ -87,7 +87,6 @@ mcview_set_buttonbar (mcview_t *view)
|
|||
buttonbar_set_label (b, 2, "", keymap, (Widget *) view);
|
||||
|
||||
buttonbar_set_label (b, 4, Q_ ("ButtonBar|Ascii"), keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 5, Q_ ("ButtonBar|Goto"), keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 6, Q_ ("ButtonBar|Save"), keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 7, Q_ ("ButtonBar|HxSrch"), keymap, (Widget *) view);
|
||||
|
||||
|
@ -96,11 +95,11 @@ mcview_set_buttonbar (mcview_t *view)
|
|||
: Q_ ("ButtonBar|Wrap"),
|
||||
keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 4, Q_ ("ButtonBar|Hex"), keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 5, Q_ ("ButtonBar|Line"), keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 6, "", keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 7, Q_ ("ButtonBar|Search"), keymap, (Widget *) view);
|
||||
}
|
||||
|
||||
buttonbar_set_label (b, 5, Q_ ("ButtonBar|Goto"), keymap, (Widget *) view);
|
||||
buttonbar_set_label (b, 8, view->magic_mode ? Q_ ("ButtonBar|Raw")
|
||||
: Q_ ("ButtonBar|Parse"),
|
||||
keymap, (Widget *) view);
|
||||
|
@ -127,10 +126,8 @@ mcview_display_status (mcview_t * view)
|
|||
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;
|
||||
const char *file_label;
|
||||
screen_dimen file_label_width, i = 0;
|
||||
|
||||
if (height < 1)
|
||||
return;
|
||||
|
@ -139,46 +136,33 @@ mcview_display_status (mcview_t * view)
|
|||
widget_move (view, top, left);
|
||||
tty_draw_hline (-1, -1, ' ', width);
|
||||
|
||||
file_label = _("File: %s");
|
||||
file_label = view->filename ? view->filename : view->command ? view->command : "";
|
||||
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);
|
||||
if (width > 40) {
|
||||
char buffer [BUF_TINY];
|
||||
widget_move (view, top, width - 32);
|
||||
if (view->hex_mode) {
|
||||
tty_printf ("0x%08lx", (unsigned long) view->hex_cursor);
|
||||
} else {
|
||||
size_trunc_len (buffer, 5, mcview_get_filesize (view), 0);
|
||||
tty_printf ("%9lli/%s%s %s", view->dpy_end,
|
||||
buffer,
|
||||
mcview_may_still_grow (view) ? "+" : " ",
|
||||
#ifdef HAVE_CHARSET
|
||||
source_codepage >= 0 ? get_codepage_id (source_codepage) : ""
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
tty_setcolor (SELECTED_COLOR);
|
||||
widget_move (view, top, left);
|
||||
if (width > 40)
|
||||
tty_print_string (str_fit_to_term (file_label, width - 34, J_LEFT_FIT));
|
||||
else
|
||||
tty_print_string (str_fit_to_term (file_label, width - 5, J_LEFT_FIT));
|
||||
if (width > 26)
|
||||
mcview_percent (view, view->hex_mode ? view->hex_cursor : view->dpy_end);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -206,8 +190,7 @@ mcview_update (mcview_t * view)
|
|||
dirt_limit++;
|
||||
if (dirt_limit > mcview_max_dirt_limit)
|
||||
dirt_limit = mcview_max_dirt_limit;
|
||||
}
|
||||
if (view->dirty) {
|
||||
} else if (view->dirty > 0) {
|
||||
if (is_idle ()) {
|
||||
/* We have time to update the screen properly */
|
||||
mcview_display (view);
|
||||
|
|
|
@ -38,7 +38,6 @@ enum view_ds {
|
|||
DS_STRING /* Data comes from a string in memory */
|
||||
};
|
||||
|
||||
|
||||
enum ccache_type {
|
||||
CCACHE_OFFSET,
|
||||
CCACHE_LINECOL
|
||||
|
@ -64,18 +63,23 @@ struct area {
|
|||
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 {
|
||||
typedef struct {
|
||||
off_t cc_offset;
|
||||
off_t cc_line;
|
||||
off_t cc_column;
|
||||
off_t cc_nroff_column;
|
||||
};
|
||||
} coord_cache_entry_t;
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
coord_cache_entry_t **cache;
|
||||
} coord_cache_t;
|
||||
|
||||
struct mcview_nroff_struct;
|
||||
|
||||
|
@ -123,7 +127,7 @@ typedef struct mcview_struct {
|
|||
|
||||
/* Additional editor state */
|
||||
gboolean hexedit_lownibble; /* Are we editing the last significant nibble? */
|
||||
GArray *coord_cache; /* Cache for mapping offsets to cursor positions */
|
||||
coord_cache_t *coord_cache; /* Cache for mapping offsets to cursor positions */
|
||||
|
||||
/* Display information */
|
||||
screen_dimen dpy_frame_size; /* Size of the frame surrounding the real viewer */
|
||||
|
@ -205,19 +209,20 @@ cb_ret_t mcview_dialog_callback (Dlg_head *h, Widget *sender,
|
|||
dlg_msg_t msg, int parm, void *data);
|
||||
|
||||
/* coord_cache.c: */
|
||||
gboolean mcview_coord_cache_entry_less (const struct coord_cache_entry *,
|
||||
const struct coord_cache_entry *, enum ccache_type,
|
||||
gboolean);
|
||||
coord_cache_t *coord_cache_new (void);
|
||||
void coord_cache_free (coord_cache_t *cache);
|
||||
|
||||
#ifdef MC_ENABLE_DEBUGGING_CODE
|
||||
void mcview_ccache_dump (mcview_t *view);
|
||||
#endif
|
||||
|
||||
void mcview_ccache_lookup (mcview_t *view, struct coord_cache_entry *coord,
|
||||
void mcview_ccache_lookup (mcview_t *view, coord_cache_entry_t *coord,
|
||||
enum ccache_type lookup_what);
|
||||
|
||||
/* datasource.c: */
|
||||
void mcview_set_datasource_none (mcview_t *);
|
||||
off_t mcview_get_filesize (mcview_t *);
|
||||
void mcview_update_filesize (mcview_t * view);
|
||||
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 *);
|
||||
|
@ -232,7 +237,8 @@ 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 *);
|
||||
gboolean mcview_dialog_search (mcview_t *view);
|
||||
gboolean mcview_dialog_goto (mcview_t *view, off_t *offset);
|
||||
|
||||
/* display.c: */
|
||||
void mcview_update (mcview_t *view);
|
||||
|
@ -269,6 +275,8 @@ void mcview_done (mcview_t *view);
|
|||
void mcview_select_encoding (mcview_t *view);
|
||||
void mcview_set_codeset (mcview_t *view);
|
||||
void mcview_show_error (mcview_t *view, const char *error);
|
||||
off_t mcview_bol (mcview_t *view, off_t current);
|
||||
off_t mcview_eol (mcview_t *view, off_t current);
|
||||
|
||||
/* move.c */
|
||||
void mcview_move_up (mcview_t *, off_t);
|
||||
|
|
|
@ -92,14 +92,6 @@ 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++;
|
||||
}
|
||||
|
@ -169,11 +161,8 @@ 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);
|
||||
save_file_position (canon_fname, -1, 0, view->dpy_start);
|
||||
g_free (canon_fname);
|
||||
}
|
||||
|
||||
|
@ -193,9 +182,7 @@ mcview_done (mcview_t * view)
|
|||
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;
|
||||
}
|
||||
coord_cache_free (view->coord_cache), view->coord_cache = NULL;
|
||||
|
||||
if (!(view->converter == INVALID_CONV || view->converter != str_cnv_from_term)) {
|
||||
str_close_conv (view->converter);
|
||||
|
@ -258,3 +245,60 @@ mcview_show_error (mcview_t * view, const char *msg)
|
|||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* returns index of the first char in the line */
|
||||
/* it is constant for all line characters */
|
||||
off_t
|
||||
mcview_bol (mcview_t * view, off_t current)
|
||||
{
|
||||
int c;
|
||||
off_t filesize;
|
||||
filesize = mcview_get_filesize (view);
|
||||
if (current <= 0)
|
||||
return 0;
|
||||
if (current > filesize)
|
||||
return filesize;
|
||||
if (!mcview_get_byte (view, current, &c))
|
||||
return current;
|
||||
if (c == '\n') {
|
||||
if (!mcview_get_byte (view, current - 1, &c))
|
||||
return current;
|
||||
if (c == '\r')
|
||||
current--;
|
||||
}
|
||||
while (current > 0) {
|
||||
if (!mcview_get_byte (view, current - 1, &c))
|
||||
break;
|
||||
if (c == '\r' || c == '\n')
|
||||
break;
|
||||
current--;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/* returns index of last char on line + width EOL */
|
||||
/* mcview_eol of the current line == mcview_bol next line */
|
||||
off_t
|
||||
mcview_eol (mcview_t * view, off_t current)
|
||||
{
|
||||
int c, prev_ch = 0;
|
||||
off_t filesize;
|
||||
filesize = mcview_get_filesize (view);
|
||||
if (current < 0)
|
||||
return 0;
|
||||
if (current >= filesize)
|
||||
return filesize;
|
||||
while (current < filesize) {
|
||||
if (!mcview_get_byte (view, current, &c))
|
||||
break;
|
||||
if (c == '\n') {
|
||||
current++;
|
||||
break;
|
||||
} else if (prev_ch == '\r') {
|
||||
break;
|
||||
}
|
||||
current++;
|
||||
prev_ch = c;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ int mcview_max_dirt_limit = 10;
|
|||
/* Scrolling is done in pages or line increments */
|
||||
int mcview_mouse_move_pages = 1;
|
||||
|
||||
/* end of file will be showen from mcview_show_eof */
|
||||
char *mcview_show_eof = NULL;
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
|
@ -379,11 +381,12 @@ mcview_load (mcview_t * view, const char *command, const char *file, int start_l
|
|||
|
||||
if (mcview_remember_file_position && view->filename != NULL && start_line == 0) {
|
||||
long line, col;
|
||||
|
||||
off_t new_offset;
|
||||
canon_fname = vfs_canon (view->filename);
|
||||
load_file_position (canon_fname, &line, &col);
|
||||
load_file_position (canon_fname, &line, &col, &new_offset);
|
||||
new_offset = min (new_offset, mcview_get_filesize (view));
|
||||
view->dpy_start = mcview_bol (view, new_offset);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ extern int mcview_remember_file_position;
|
|||
extern int mcview_max_dirt_limit;
|
||||
|
||||
extern int mcview_mouse_move_pages;
|
||||
extern char *mcview_show_eof;
|
||||
|
||||
/*** declarations of public functions **********************************/
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
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>
|
||||
2009, 2010 Ilia Maslakov <il.smind@gmail.com>
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
|
@ -87,6 +87,7 @@ mcview_movement_fixups (mcview_t * view, gboolean reset_search)
|
|||
void
|
||||
mcview_move_up (mcview_t * view, off_t lines)
|
||||
{
|
||||
off_t new_offset;
|
||||
if (view->hex_mode) {
|
||||
off_t bytes = lines * view->bytes_per_line;
|
||||
if (view->hex_cursor >= bytes) {
|
||||
|
@ -96,38 +97,19 @@ mcview_move_up (mcview_t * view, off_t lines)
|
|||
} 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);
|
||||
off_t i;
|
||||
for (i = 0; i < lines; i++) {
|
||||
new_offset = mcview_bol (view, view->dpy_start);
|
||||
if (new_offset > 0)
|
||||
new_offset--;
|
||||
new_offset = mcview_bol (view, new_offset);
|
||||
if (new_offset < 0)
|
||||
new_offset = 0;
|
||||
view->dpy_start = new_offset;
|
||||
}
|
||||
}
|
||||
mcview_movement_fixups (view, (lines != 1));
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -135,10 +117,11 @@ mcview_move_up (mcview_t * view, off_t lines)
|
|||
void
|
||||
mcview_move_down (mcview_t * view, off_t lines)
|
||||
{
|
||||
off_t last_byte;
|
||||
last_byte = mcview_get_filesize (view);
|
||||
if (view->hex_mode) {
|
||||
off_t i, limit, last_byte;
|
||||
off_t i, limit;
|
||||
|
||||
last_byte = mcview_get_filesize (view);
|
||||
if (last_byte >= (off_t) view->bytes_per_line)
|
||||
limit = last_byte - view->bytes_per_line;
|
||||
else
|
||||
|
@ -148,39 +131,15 @@ mcview_move_down (mcview_t * view, off_t lines)
|
|||
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;
|
||||
|
||||
} else {
|
||||
off_t i;
|
||||
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++;
|
||||
|
||||
off_t new_offset;
|
||||
new_offset = mcview_eol (view, view->dpy_start);
|
||||
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));
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -189,13 +148,15 @@ void
|
|||
mcview_move_left (mcview_t * view, off_t columns)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
off_t old_cursor = view->hex_cursor;
|
||||
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;
|
||||
if (old_cursor > 0 || view->hexedit_lownibble)
|
||||
view->hexedit_lownibble = !view->hexedit_lownibble;
|
||||
} else if (view->text_wrap_mode) {
|
||||
/* nothing to do */
|
||||
} else {
|
||||
|
@ -213,12 +174,17 @@ void
|
|||
mcview_move_right (mcview_t * view, off_t columns)
|
||||
{
|
||||
if (view->hex_mode) {
|
||||
off_t last_byte;
|
||||
off_t old_cursor = view->hex_cursor;
|
||||
last_byte = mcview_offset_doz(mcview_get_filesize (view), 1);
|
||||
assert (columns == 1);
|
||||
if (view->hexview_in_text || view->hexedit_lownibble) {
|
||||
view->hex_cursor++;
|
||||
if (view->hex_cursor < last_byte)
|
||||
view->hex_cursor++;
|
||||
}
|
||||
if (!view->hexview_in_text)
|
||||
view->hexedit_lownibble = !view->hexedit_lownibble;
|
||||
if (old_cursor < last_byte || !view->hexedit_lownibble)
|
||||
view->hexedit_lownibble = !view->hexedit_lownibble;
|
||||
} else if (view->text_wrap_mode) {
|
||||
/* nothing to do */
|
||||
} else {
|
||||
|
@ -244,17 +210,6 @@ mcview_scroll_to_cursor (mcview_t * view)
|
|||
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 */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,24 +231,24 @@ mcview_moveto_bottom (mcview_t * view)
|
|||
{
|
||||
off_t datalines, lines_up, filesize, last_offset;
|
||||
|
||||
mcview_update_filesize (view);
|
||||
|
||||
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) {
|
||||
last_offset = mcview_offset_doz (filesize, 1);
|
||||
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);
|
||||
view->dpy_start = filesize;
|
||||
mcview_move_up (view, 1);
|
||||
}
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -303,13 +258,8 @@ 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;
|
||||
} else if (!view->text_wrap_mode) {
|
||||
view->dpy_start = mcview_bol (view, view->dpy_start);
|
||||
}
|
||||
mcview_movement_fixups (view, TRUE);
|
||||
}
|
||||
|
@ -329,13 +279,6 @@ mcview_moveto_eol (mcview_t * view)
|
|||
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);
|
||||
}
|
||||
|
@ -370,7 +313,7 @@ mcview_moveto (mcview_t * view, off_t line, off_t col)
|
|||
void
|
||||
mcview_coord_to_offset (mcview_t * view, off_t * ret_offset, off_t line, off_t column)
|
||||
{
|
||||
struct coord_cache_entry coord;
|
||||
coord_cache_entry_t coord;
|
||||
|
||||
coord.cc_line = line;
|
||||
coord.cc_column = column;
|
||||
|
@ -384,17 +327,14 @@ mcview_coord_to_offset (mcview_t * view, off_t * ret_offset, off_t line, off_t c
|
|||
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_cache_entry_t 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;
|
||||
*ret_line = coord.cc_line;
|
||||
*ret_column = (view->text_nroff_mode)
|
||||
? coord.cc_nroff_column : coord.cc_column;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -404,9 +344,7 @@ 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;
|
||||
screen_dimen col = view->cursor_col;
|
||||
if (!view->hexview_in_text && view->hexedit_lownibble)
|
||||
col++;
|
||||
widget_move (&view->widget, top + view->cursor_row, left + col);
|
||||
|
@ -420,19 +358,15 @@ mcview_place_cursor (mcview_t * view)
|
|||
void
|
||||
mcview_moveto_match (mcview_t * view)
|
||||
{
|
||||
off_t search_line, search_col, offset;
|
||||
off_t 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);
|
||||
offset = view->search_start;
|
||||
|
||||
if (view->hex_mode) {
|
||||
view->hex_cursor = offset;
|
||||
view->dpy_start = offset - offset % view->bytes_per_line;
|
||||
} else {
|
||||
view->dpy_start = offset;
|
||||
view->dpy_start = mcview_bol (view, offset);
|
||||
}
|
||||
|
||||
mcview_scroll_to_cursor (view);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "../src/main.h"
|
||||
#include "../src/charsets.h"
|
||||
#include "../src/util.h" /* is_printable() */
|
||||
#include "mcviewer.h" /* mcview_show_eof */
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
@ -74,6 +75,7 @@ mcview_display_text (mcview_t * view)
|
|||
off_t from;
|
||||
int cw = 1;
|
||||
int c, prev_ch = 0;
|
||||
gboolean last_row = TRUE;
|
||||
struct hexedit_change_node *curr = view->change_list;
|
||||
|
||||
mcview_display_clean (view);
|
||||
|
@ -102,6 +104,7 @@ mcview_display_text (mcview_t * view)
|
|||
if (!mcview_get_byte (view, from, &c))
|
||||
break;
|
||||
|
||||
last_row = FALSE;
|
||||
from++;
|
||||
if (cw > 1)
|
||||
from += cw - 1;
|
||||
|
@ -131,8 +134,6 @@ mcview_display_text (mcview_t * view)
|
|||
}
|
||||
|
||||
if (c == '\t') {
|
||||
off_t line, column;
|
||||
mcview_offset_to_coord (view, &line, &column, from);
|
||||
col += (option_tab_spacing - col % option_tab_spacing);
|
||||
if (view->text_wrap_mode && col >= width && width != 0) {
|
||||
row += col / width;
|
||||
|
@ -179,6 +180,15 @@ mcview_display_text (mcview_t * view)
|
|||
}
|
||||
|
||||
view->dpy_end = from;
|
||||
if (mcview_show_eof != NULL && mcview_show_eof[0] != '\0') {
|
||||
if (last_row && mcview_get_byte (view, from - 1, &c))
|
||||
if (c != '\n')
|
||||
row--;
|
||||
while (++row < height) {
|
||||
widget_move (view, top + row, left);
|
||||
tty_print_string (mcview_show_eof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
|
Loading…
Reference in New Issue