Merge branch '4132_tags_dialog_width'

* 4132_tags_dialog_width:
  etags: get rid of limitation of window width.
  etags: get rid of limitation of definition length.
  etags: get rid of limitation of list length.
  etags: fix memory leaks.
  (etags_hash_t): remove unused filename_len member.
  Ticket #4132: clarify width of 'Find declaration' dialog.
This commit is contained in:
Andrew Borodin 2021-03-13 20:36:19 +03:00
commit 32c28026f8
5 changed files with 167 additions and 140 deletions

View File

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

View File

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

View File

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

View File

@ -31,11 +31,10 @@
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -1,26 +1,16 @@
#ifndef MC__EDIT_ETAGS_H
#define MC__EDIT_ETAGS_H 1
#include <sys/types.h> /* size_t */
#include "lib/global.h" /* include <glib.h> */
/*** 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 */