From e3589ee4d89f66bf5f1103b9632d8bab50e9ffb9 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 12 Jan 2010 11:28:03 +0000 Subject: [PATCH] New 'Goto' dialog implementation in viewer. Signed-off-by: Andrew Borodin Removed mcview_moveto_addr_cmd, mcview_moveto_line_cmd, mcview_moveto_cmd. Signed-off-by: Ilia Maslakov --- src/history.h | 1 + src/viewer/actions_cmd.c | 59 +++------------ src/viewer/dialogs.c | 158 +++++++++++++++++++++++++++++++++++---- src/viewer/internal.h | 5 +- 4 files changed, 157 insertions(+), 66 deletions(-) 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/viewer/actions_cmd.c b/src/viewer/actions_cmd.c index 0927721b5..0a76fd44b 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) { @@ -359,13 +315,20 @@ mcview_execute_cmd (mcview_t *view, unsigned long command) mcview_update (view); /* FIXME: view->dirty++ ? */ break; case CK_ViewGoto: - if (view->hex_mode) - mcview_moveto_addr_cmd (view); - else - mcview_moveto_line_cmd (view); + { + off_t addr; + + if (mcview_dialog_goto (view, &addr)) { + if (addr < 0) + message (D_ERROR, _("Warning"), _("Invalid value")); + else + mcview_moveto_offset (view, addr); + } + view->dirty++; mcview_update (view); /* FIXME: unneeded? */ break; + } case CK_ViewHexEditSave: mcview_hexedit_save_changes (view); break; 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/internal.h b/src/viewer/internal.h index 39f71a41f..6c229df94 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,7 +63,6 @@ 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 @@ -238,7 +236,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);