diff --git a/src/editor/editcmd.c b/src/editor/editcmd.c index 4f3f06e35..48976c2d0 100644 --- a/src/editor/editcmd.c +++ b/src/editor/editcmd.c @@ -3591,19 +3591,14 @@ edit_load_back_cmd (WEdit * edit) void edit_get_match_keyword_cmd (WEdit * edit) { - gsize word_len = 0, max_len = 0; - int num_def = 0; + gsize word_len = 0; gsize i; off_t word_start = 0; GString *match_expr; char *path = NULL; char *ptr = NULL; char *tagfile = NULL; - - etags_hash_t def_hash[MAX_DEFINITIONS]; - - for (i = 0; i < MAX_DEFINITIONS; i++) - def_hash[i].filename = NULL; + GPtrArray *def_hash = NULL; /* search start of word to be completed */ if (!edit_find_word_start (&edit->buffer, &word_start, &word_len)) @@ -3633,17 +3628,18 @@ edit_get_match_keyword_cmd (WEdit * edit) if (tagfile != NULL) { - num_def = - etags_set_definition_hash (tagfile, path, match_expr->str, (etags_hash_t *) & def_hash); + def_hash = etags_set_definition_hash (tagfile, path, match_expr->str); g_free (tagfile); } g_free (path); - max_len = MAX_WIDTH_DEF_DIALOG; - word_len = 0; - if (num_def > 0) - editcmd_dialog_select_definition_show (edit, match_expr->str, max_len, word_len, - (etags_hash_t *) & def_hash, num_def); + if (def_hash != NULL) + { + editcmd_dialog_select_definition_show (edit, match_expr->str, def_hash); + + g_ptr_array_free (def_hash, TRUE); + } + g_string_free (match_expr, TRUE); } diff --git a/src/editor/editcmd_dialogs.c b/src/editor/editcmd_dialogs.c index 764a09a7e..8ee3a4db7 100644 --- a/src/editor/editcmd_dialogs.c +++ b/src/editor/editcmd_dialogs.c @@ -64,6 +64,9 @@ edit_search_options_t edit_search_options = { /*** file scope variables ************************************************************************/ +static int def_max_width; + +/* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -84,6 +87,25 @@ editcmd_dialog_raw_key_query_cb (Widget * w, Widget * sender, widget_msg_t msg, } } +/* --------------------------------------------------------------------------------------------- */ + +static void +editcmd_dialog_select_definition_add (gpointer data, gpointer user_data) +{ + etags_hash_t *def_hash = (etags_hash_t *) data; + WListbox *def_list = (WListbox *) user_data; + char *label_def; + int def_width; + + label_def = + g_strdup_printf ("%s -> %s:%ld", def_hash->short_define, def_hash->filename, + def_hash->line); + listbox_add_item (def_list, LISTBOX_APPEND_AT_END, 0, label_def, def_hash, FALSE); + def_width = str_term_width1 (label_def); + g_free (label_def); + def_max_width = MAX (def_max_width, def_width); +} + /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -411,34 +433,31 @@ editcmd_dialog_completion_show (const WEdit * edit, GQueue * compl, int max_widt /* let the user select where function definition */ void -editcmd_dialog_select_definition_show (WEdit * edit, char *match_expr, int max_len, int word_len, - etags_hash_t * def_hash, int num_lines) +editcmd_dialog_select_definition_show (WEdit * edit, char *match_expr, GPtrArray * def_hash) { - int start_x, start_y, offset, i; + const Widget *we = CONST_WIDGET (edit); + int start_x, start_y, offset; char *curr = NULL; WDialog *def_dlg; WListbox *def_list; int def_dlg_h; /* dialog height */ int def_dlg_w; /* dialog width */ - (void) word_len; /* calculate the dialog metrics */ - def_dlg_h = num_lines + 2; - def_dlg_w = max_len + 4; - start_x = edit->curs_col + edit->start_col - (def_dlg_w / 2) + - EDIT_TEXT_HORIZONTAL_OFFSET + (edit->fullscreen ? 0 : 1) + option_line_state_width; - start_y = edit->curs_row + EDIT_TEXT_VERTICAL_OFFSET + (edit->fullscreen ? 0 : 1) + 1; + def_dlg_h = def_hash->len + 2; + def_dlg_w = COLS - 2; /* will be clarified later */ + start_x = we->x + edit->curs_col + edit->start_col + EDIT_TEXT_HORIZONTAL_OFFSET + + (edit->fullscreen ? 0 : 1) + option_line_state_width; + start_y = we->y + edit->curs_row + EDIT_TEXT_VERTICAL_OFFSET + (edit->fullscreen ? 0 : 1) + 1; if (start_x < 0) start_x = 0; - if (def_dlg_w > COLS) - def_dlg_w = COLS; + if (start_x < we->x + 1) + start_x = we->x + 1 + option_line_state_width; + if (def_dlg_h > LINES - 2) def_dlg_h = LINES - 2; - offset = start_x + def_dlg_w - COLS; - if (offset > 0) - start_x -= offset; offset = start_y + def_dlg_h - LINES; if (offset > 0) start_y -= (offset + 1); @@ -446,19 +465,19 @@ editcmd_dialog_select_definition_show (WEdit * edit, char *match_expr, int max_l def_dlg = dlg_create (TRUE, start_y, start_x, def_dlg_h, def_dlg_w, WPOS_KEEP_DEFAULT, TRUE, dialog_colors, NULL, NULL, "[Definitions]", match_expr); def_list = listbox_new (1, 1, def_dlg_h - 2, def_dlg_w - 2, FALSE, NULL); - group_add_widget (GROUP (def_dlg), def_list); + group_add_widget_autopos (GROUP (def_dlg), def_list, WPOS_KEEP_ALL, NULL); - /* fill the listbox with the completions */ - for (i = 0; i < num_lines; i++) - { - char *label_def; + /* fill the listbox with the completions and get the maximim width */ + def_max_width = 0; + g_ptr_array_foreach (def_hash, editcmd_dialog_select_definition_add, def_list); - label_def = - g_strdup_printf ("%s -> %s:%ld", def_hash[i].short_define, def_hash[i].filename, - def_hash[i].line); - listbox_add_item (def_list, LISTBOX_APPEND_AT_END, 0, label_def, &def_hash[i], FALSE); - g_free (label_def); - } + /* adjust dialog width */ + def_dlg_w = def_max_width + 4; + offset = start_x + def_dlg_w - COLS; + if (offset > 0) + start_x -= offset; + + widget_set_size (WIDGET (def_dlg), start_y, start_x, def_dlg_h, def_dlg_w); /* pop up the dialog and apply the chosen completion */ if (dlg_run (def_dlg) == B_ENTER) @@ -503,10 +522,6 @@ editcmd_dialog_select_definition_show (WEdit * edit, char *match_expr, int max_l } } - /* clear definition hash */ - for (i = 0; i < MAX_DEFINITIONS; i++) - g_free (def_hash[i].filename); - /* destroy dialog before return */ dlg_destroy (def_dlg); } diff --git a/src/editor/editcmd_dialogs.h b/src/editor/editcmd_dialogs.h index 173e2ac6e..149ebc9ad 100644 --- a/src/editor/editcmd_dialogs.h +++ b/src/editor/editcmd_dialogs.h @@ -27,8 +27,7 @@ int editcmd_dialog_raw_key_query (const char *heading, const char *query, gboole char *editcmd_dialog_completion_show (const WEdit * edit, GQueue * compl, int max_width); -void editcmd_dialog_select_definition_show (WEdit *, char *, int, int, struct etags_hash_struct *, - int); +void editcmd_dialog_select_definition_show (WEdit * edit, char *match_expr, GPtrArray * def_hash); int editcmd_dialog_replace_prompt_show (WEdit *, char *, char *, int, int); /*** inline functions ****************************************************************************/ diff --git a/src/editor/etags.c b/src/editor/etags.c index 35c7a2f04..7f1394ea1 100644 --- a/src/editor/etags.c +++ b/src/editor/etags.c @@ -31,11 +31,10 @@ #include -#include -#include -#include -#include #include +#include +#include +#include #include "lib/global.h" #include "lib/util.h" /* canonicalize_pathname() */ @@ -50,9 +49,23 @@ /*** file scope variables ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +static void +etags_hash_free (gpointer data) +{ + etags_hash_t *hash = (etags_hash_t *) data; + + g_free (hash->filename); + g_free (hash->fullpath); + g_free (hash->short_define); + g_free (hash); +} + +/* --------------------------------------------------------------------------------------------- */ + static gboolean parse_define (const char *buf, char **long_name, char **short_name, long *line) { @@ -62,16 +75,15 @@ parse_define (const char *buf, char **long_name, char **short_name, long *line) in_longname, in_shortname, in_shortname_first_char, - in_line, finish + in_line, + finish } def_state = in_longname; /* *INDENT-ON* */ - static char longdef[LONG_DEF_LEN]; - static char shortdef[SHORT_DEF_LEN]; - static char linedef[LINE_DEF_LEN]; - int nlong = 0; - int nshort = 0; - int nline = 0; + GString *longdef = NULL; + GString *shortdef = NULL; + GString *linedef = NULL; + char c = *buf; while (!(c == '\0' || c == '\n')) @@ -80,88 +92,92 @@ parse_define (const char *buf, char **long_name, char **short_name, long *line) { case in_longname: if (c == 0x01) - { def_state = in_line; - } else if (c == 0x7F) - { def_state = in_shortname; - } else { - if (nlong < LONG_DEF_LEN - 1) - { - longdef[nlong++] = c; - } + if (longdef == NULL) + longdef = g_string_sized_new (32); + + g_string_append_c (longdef, c); } break; + case in_shortname_first_char: if (isdigit (c)) { - nshort = 0; + if (shortdef == NULL) + shortdef = g_string_sized_new (32); + else + g_string_set_size (shortdef, 0); + buf--; def_state = in_line; } else if (c == 0x01) - { def_state = in_line; - } else { - if (nshort < SHORT_DEF_LEN - 1) - { - shortdef[nshort++] = c; - def_state = in_shortname; - } + if (shortdef == NULL) + shortdef = g_string_sized_new (32); + + g_string_append_c (shortdef, c); + def_state = in_shortname; } break; + case in_shortname: if (c == 0x01) - { def_state = in_line; - } else if (c == '\n') - { def_state = finish; - } else { - if (nshort < SHORT_DEF_LEN - 1) - { - shortdef[nshort++] = c; - } + if (shortdef == NULL) + shortdef = g_string_sized_new (32); + + g_string_append_c (shortdef, c); } break; + case in_line: if (c == ',' || c == '\n') - { def_state = finish; - } else if (isdigit (c)) { - if (nline < LINE_DEF_LEN - 1) - { - linedef[nline++] = c; - } + if (linedef == NULL) + linedef = g_string_sized_new (32); + + g_string_append_c (linedef, c); } break; + case finish: - longdef[nlong] = '\0'; - shortdef[nshort] = '\0'; - linedef[nline] = '\0'; - *long_name = longdef; - *short_name = shortdef; - *line = atol (linedef); + *long_name = longdef == NULL ? NULL : g_string_free (longdef, FALSE); + *short_name = shortdef == NULL ? NULL : g_string_free (shortdef, FALSE); + + if (linedef == NULL) + *line = 0; + else + { + *line = atol (linedef->str); + g_string_free (linedef, TRUE); + } return TRUE; + default: break; } + buf++; c = *buf; } + *long_name = NULL; *short_name = NULL; *line = 0; + return FALSE; } @@ -169,9 +185,8 @@ parse_define (const char *buf, char **long_name, char **short_name, long *line) /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ -int -etags_set_definition_hash (const char *tagfile, const char *start_path, - const char *match_func, etags_hash_t * def_hash) +GPtrArray * +etags_set_definition_hash (const char *tagfile, const char *start_path, const char *match_func) { /* *INDENT-OFF* */ enum @@ -184,30 +199,25 @@ etags_set_definition_hash (const char *tagfile, const char *start_path, FILE *f; char buf[BUF_LARGE]; - - char *chekedstr = NULL; - - int num = 0; /* returned value */ char *filename = NULL; + GPtrArray *ret = NULL; - if (!match_func || !tagfile) - return 0; + if (match_func == NULL || tagfile == NULL) + return NULL; /* open file with positions */ f = fopen (tagfile, "r"); if (f == NULL) - return 0; + return NULL; - while (fgets (buf, sizeof (buf), f)) - { + while (fgets (buf, sizeof (buf), f) != NULL) switch (state) { case start: if (buf[0] == 0x0C) - { state = in_filename; - } break; + case in_filename: { size_t pos; @@ -218,43 +228,59 @@ etags_set_definition_hash (const char *tagfile, const char *start_path, state = in_define; break; } + case in_define: if (buf[0] == 0x0C) - { state = in_filename; - break; - } - /* check if the filename matches the define pos */ - chekedstr = strstr (buf, match_func); - if (chekedstr) + else { - char *longname = NULL; - char *shortname = NULL; - long line = 0; + char *chekedstr; - parse_define (chekedstr, &longname, &shortname, &line); - if (num < MAX_DEFINITIONS - 1) + /* check if the filename matches the define pos */ + chekedstr = strstr (buf, match_func); + if (chekedstr != NULL) { - def_hash[num].filename_len = strlen (filename); - def_hash[num].fullpath = - mc_build_filename (start_path, filename, (char *) NULL); + char *longname = NULL; + char *shortname = NULL; + etags_hash_t *def_hash; - canonicalize_pathname (def_hash[num].fullpath); - def_hash[num].filename = g_strdup (filename); - def_hash[num].short_define = g_strdup (shortname ? shortname : longname); - def_hash[num].line = line; - num++; + def_hash = g_new (etags_hash_t, 1); + + def_hash->fullpath = mc_build_filename (start_path, filename, (char *) NULL); + canonicalize_pathname (def_hash->fullpath); + def_hash->filename = g_strdup (filename); + + def_hash->line = 0; + + parse_define (chekedstr, &longname, &shortname, &def_hash->line); + + if (shortname != NULL && *shortname != '\0') + { + def_hash->short_define = shortname; + g_free (longname); + } + else + { + def_hash->short_define = longname; + g_free (shortname); + } + + if (ret == NULL) + ret = g_ptr_array_new_with_free_func (etags_hash_free); + + g_ptr_array_add (ret, def_hash); } } break; + default: break; } - } g_free (filename); fclose (f); - return num; + + return ret; } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/editor/etags.h b/src/editor/etags.h index be71b3a27..d153514f1 100644 --- a/src/editor/etags.h +++ b/src/editor/etags.h @@ -1,26 +1,16 @@ #ifndef MC__EDIT_ETAGS_H #define MC__EDIT_ETAGS_H 1 -#include /* size_t */ -#include "lib/global.h" /* include */ - /*** typedefs(not structures) and defined constants **********************************************/ -#define MAX_WIDTH_DEF_DIALOG 60 /* max width def dialog */ -#define MAX_DEFINITIONS 60 /* count found entries show */ -#define SHORT_DEF_LEN 30 -#define LONG_DEF_LEN 40 -#define LINE_DEF_LEN 16 - /*** enums ***************************************************************************************/ /*** structures declarations (and typedefs of structures)*****************************************/ typedef struct etags_hash_struct { - size_t filename_len; - char *fullpath; char *filename; + char *fullpath; char *short_define; long line; } etags_hash_t; @@ -30,8 +20,9 @@ typedef struct etags_hash_struct /*** declarations of public functions ************************************************************/ -int etags_set_definition_hash (const char *tagfile, const char *start_path, - const char *match_func, etags_hash_t * def_hash); +GPtrArray *etags_set_definition_hash (const char *tagfile, const char *start_path, + const char *match_func); /*** inline functions ****************************************************************************/ + #endif /* MC__EDIT_ETAGS_H */