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:
Ilia Maslakov 2010-01-19 19:21:04 +00:00
commit 4c6b5fc569
16 changed files with 518 additions and 328 deletions

View File

@ -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);
}

View File

@ -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"

View File

@ -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 }
};

View File

@ -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;
}

View File

@ -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 */

View File

@ -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:

View File

@ -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, &current);
}
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 (&current, coord, sorter, view->text_nroff_mode)) {
if (lookup_what == CCACHE_OFFSET && view->text_nroff_mode && nroff_state != NROFF_START) {
if (!cmp_func (&current, 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;

View File

@ -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)
{

View File

@ -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 *) &current_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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 **********************************/

View File

@ -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);

View File

@ -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);
}
}
}
/* --------------------------------------------------------------------------------------------- */