diff --git a/edit/edit.c b/edit/edit.c index b8af0a361..63b45701e 100644 --- a/edit/edit.c +++ b/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); } diff --git a/src/history.h b/src/history.h index 85cfcc9d1..66c809a0d 100644 --- a/src/history.h +++ b/src/history.h @@ -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" diff --git a/src/setup.c b/src/setup.c index d25833b5b..7ea8ed5ca 100644 --- a/src/setup.c +++ b/src/setup.c @@ -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 } }; diff --git a/src/util.c b/src/util.c index 47f87786d..a38f3e83f 100644 --- a/src/util.c +++ b/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) @@ -1384,14 +1386,26 @@ load_file_position (const char *filename, long *line, long *column) p = &buf[len + 1]; 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; } diff --git a/src/util.h b/src/util.h index 0867cd7b5..829a32c69 100644 --- a/src/util.h +++ b/src/util.h @@ -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 */ diff --git a/src/viewer/actions_cmd.c b/src/viewer/actions_cmd.c index 0927721b5..6d6fb9020 100644 --- a/src/viewer/actions_cmd.c +++ b/src/viewer/actions_cmd.c @@ -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: diff --git a/src/viewer/coord_cache.c b/src/viewer/coord_cache.c index bbd0c80d9..35acef38d 100644 --- a/src/viewer/coord_cache.c +++ b/src/viewer/coord_cache.c @@ -51,39 +51,106 @@ #include +#include /* 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; diff --git a/src/viewer/datasource.c b/src/viewer/datasource.c index d2d689a3b..668e05846 100644 --- a/src/viewer/datasource.c +++ b/src/viewer/datasource.c @@ -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) { diff --git a/src/viewer/dialogs.c b/src/viewer/dialogs.c index 9b96e3238..de3bafed7 100644 --- a/src/viewer/dialogs.c +++ b/src/viewer/dialogs.c @@ -40,12 +40,14 @@ #include #include +#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; } diff --git a/src/viewer/display.c b/src/viewer/display.c index 941ebf984..87a94a205 100644 --- a/src/viewer/display.c +++ b/src/viewer/display.c @@ -15,7 +15,7 @@ 2005 Roland Illig 2009 Slava Zanko 2009 Andrew Borodin - 2009 Ilia Maslakov + 2009, 2010 Ilia Maslakov 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); diff --git a/src/viewer/internal.h b/src/viewer/internal.h index 1058c133f..22391c611 100644 --- a/src/viewer/internal.h +++ b/src/viewer/internal.h @@ -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); diff --git a/src/viewer/lib.c b/src/viewer/lib.c index 4d0914001..335693dbc 100644 --- a/src/viewer/lib.c +++ b/src/viewer/lib.c @@ -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; +} diff --git a/src/viewer/mcviewer.c b/src/viewer/mcviewer.c index 715b19e1c..a2aecf408 100644 --- a/src/viewer/mcviewer.c +++ b/src/viewer/mcviewer.c @@ -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); } diff --git a/src/viewer/mcviewer.h b/src/viewer/mcviewer.h index f3bbd2133..89ba27727 100644 --- a/src/viewer/mcviewer.h +++ b/src/viewer/mcviewer.h @@ -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 **********************************/ diff --git a/src/viewer/move.c b/src/viewer/move.c index 96455e84f..ea6e5e035 100644 --- a/src/viewer/move.c +++ b/src/viewer/move.c @@ -15,7 +15,7 @@ 2005 Roland Illig 2009 Slava Zanko 2009 Andrew Borodin - 2009 Ilia Maslakov + 2009, 2010 Ilia Maslakov 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); diff --git a/src/viewer/plain.c b/src/viewer/plain.c index 6df36e6fd..f9dd8302d 100644 --- a/src/viewer/plain.c +++ b/src/viewer/plain.c @@ -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); + } + } } /* --------------------------------------------------------------------------------------------- */