2006-10-02 11:31:54 +00:00
|
|
|
/*
|
|
|
|
* symbols.c - this file is part of Geany, a fast and lightweight IDE
|
|
|
|
*
|
|
|
|
* Copyright 2006 Enrico Troeger <enrico.troeger@uvena.de>
|
|
|
|
* Copyright 2006 Nick Treleaven <nick.treleaven@btinternet.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "geany.h"
|
2006-11-08 11:42:05 +00:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
2006-10-02 11:31:54 +00:00
|
|
|
#include "symbols.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "filetypes.h"
|
2006-11-08 11:42:05 +00:00
|
|
|
#include "encodings.h"
|
|
|
|
#include "document.h"
|
2006-10-02 11:31:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
enum // Geany tag files
|
|
|
|
{
|
|
|
|
GTF_C,
|
|
|
|
GTF_PASCAL,
|
|
|
|
GTF_PHP,
|
|
|
|
GTF_HTML_ENTITIES,
|
|
|
|
GTF_LATEX,
|
|
|
|
GTF_MAX
|
|
|
|
};
|
|
|
|
|
2006-12-15 17:09:05 +00:00
|
|
|
static gchar **html_entities = NULL;
|
|
|
|
|
2006-10-02 11:31:54 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gboolean tags_loaded;
|
|
|
|
const gchar *tag_file;
|
|
|
|
} TagFileInfo;
|
|
|
|
|
|
|
|
static TagFileInfo tag_file_info[GTF_MAX] =
|
|
|
|
{
|
|
|
|
{FALSE, "global.tags"},
|
|
|
|
{FALSE, "pascal.tags"},
|
|
|
|
{FALSE, "php.tags"},
|
|
|
|
{FALSE, "html_entities.tags"},
|
|
|
|
{FALSE, "latex.tags"}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void html_tags_loaded();
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure that the global tags file for the file_type_idx filetype is loaded.
|
|
|
|
void symbols_global_tags_loaded(gint file_type_idx)
|
|
|
|
{
|
|
|
|
TagFileInfo *tfi;
|
|
|
|
gint gtf, lt;
|
|
|
|
|
|
|
|
if (app->ignore_global_tags) return;
|
|
|
|
|
|
|
|
switch (file_type_idx)
|
|
|
|
{
|
|
|
|
case GEANY_FILETYPES_HTML:
|
|
|
|
html_tags_loaded();
|
|
|
|
return;
|
2006-11-08 11:42:05 +00:00
|
|
|
case GEANY_FILETYPES_C: gtf = GTF_C; break;
|
|
|
|
case GEANY_FILETYPES_CPP: gtf = GTF_C; break;
|
|
|
|
case GEANY_FILETYPES_PASCAL:gtf = GTF_PASCAL; break;
|
|
|
|
case GEANY_FILETYPES_PHP: gtf = GTF_PHP; break;
|
|
|
|
case GEANY_FILETYPES_LATEX: gtf = GTF_LATEX; break;
|
2006-10-02 11:31:54 +00:00
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
2006-11-08 11:42:05 +00:00
|
|
|
lt = filetypes[file_type_idx]->lang;
|
2006-10-02 11:31:54 +00:00
|
|
|
tfi = &tag_file_info[gtf];
|
|
|
|
|
|
|
|
if (! tfi->tags_loaded)
|
|
|
|
{
|
|
|
|
gchar *file = g_strconcat(app->datadir, G_DIR_SEPARATOR_S, tfi->tag_file, NULL);
|
|
|
|
tm_workspace_load_global_tags(file, lt);
|
|
|
|
tfi->tags_loaded = TRUE;
|
|
|
|
g_free(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void html_tags_loaded()
|
|
|
|
{
|
|
|
|
TagFileInfo *tfi;
|
|
|
|
|
|
|
|
if (app->ignore_global_tags) return;
|
|
|
|
|
|
|
|
tfi = &tag_file_info[GTF_HTML_ENTITIES];
|
|
|
|
if (! tfi->tags_loaded)
|
|
|
|
{
|
|
|
|
gchar *file = g_strconcat(app->datadir, G_DIR_SEPARATOR_S, tfi->tag_file, NULL);
|
|
|
|
html_entities = utils_read_file_in_array(file);
|
|
|
|
tfi->tags_loaded = TRUE;
|
|
|
|
g_free(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-08 11:42:05 +00:00
|
|
|
GString *symbols_find_tags_as_string(GPtrArray *tags_array, guint tag_types)
|
2006-10-02 11:31:54 +00:00
|
|
|
{
|
2006-11-08 11:42:05 +00:00
|
|
|
guint j;
|
2006-10-02 11:31:54 +00:00
|
|
|
GString *s = NULL;
|
2006-11-08 11:42:05 +00:00
|
|
|
GPtrArray *typedefs;
|
2006-10-02 11:31:54 +00:00
|
|
|
|
2006-11-08 11:42:05 +00:00
|
|
|
g_return_val_if_fail(tags_array != NULL, NULL);
|
2006-10-02 11:31:54 +00:00
|
|
|
|
2006-11-08 11:42:05 +00:00
|
|
|
typedefs = tm_tags_extract(tags_array, tag_types);
|
|
|
|
|
|
|
|
if ((typedefs) && (typedefs->len > 0))
|
|
|
|
{
|
|
|
|
s = g_string_sized_new(typedefs->len * 10);
|
|
|
|
for (j = 0; j < typedefs->len; ++j)
|
2006-10-02 11:31:54 +00:00
|
|
|
{
|
2006-11-08 11:42:05 +00:00
|
|
|
if (!(TM_TAG(typedefs->pdata[j])->atts.entry.scope))
|
2006-10-02 11:31:54 +00:00
|
|
|
{
|
2006-11-08 11:42:05 +00:00
|
|
|
if (TM_TAG(typedefs->pdata[j])->name)
|
2006-10-02 11:31:54 +00:00
|
|
|
{
|
2006-11-08 11:42:05 +00:00
|
|
|
g_string_append(s, TM_TAG(typedefs->pdata[j])->name);
|
2006-10-02 11:31:54 +00:00
|
|
|
g_string_append_c(s, ' ');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-11-08 11:42:05 +00:00
|
|
|
g_ptr_array_free(typedefs, TRUE);
|
2006-10-02 11:31:54 +00:00
|
|
|
return s;
|
|
|
|
}
|
2006-11-08 11:42:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
const GList *symbols_get_tag_list(gint idx, guint tag_types)
|
|
|
|
{
|
|
|
|
static GList *tag_names = NULL;
|
|
|
|
|
|
|
|
if (idx >= 0 && doc_list[idx].is_valid && doc_list[idx].tm_file &&
|
|
|
|
doc_list[idx].tm_file->tags_array)
|
|
|
|
{
|
|
|
|
TMTag *tag;
|
|
|
|
guint i;
|
|
|
|
GeanySymbol *symbol;
|
|
|
|
gboolean doc_is_utf8 = FALSE;
|
|
|
|
gchar *utf8_name;
|
|
|
|
|
|
|
|
if (tag_names)
|
|
|
|
{
|
|
|
|
GList *tmp;
|
|
|
|
for (tmp = tag_names; tmp; tmp = g_list_next(tmp))
|
|
|
|
{
|
|
|
|
g_free(((GeanySymbol*)tmp->data)->str);
|
|
|
|
g_free(tmp->data);
|
|
|
|
}
|
|
|
|
g_list_free(tag_names);
|
|
|
|
tag_names = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// do this comparison only once
|
2006-12-07 16:09:45 +00:00
|
|
|
if (utils_str_equal(doc_list[idx].encoding, "UTF-8")) doc_is_utf8 = TRUE;
|
2006-11-08 11:42:05 +00:00
|
|
|
|
|
|
|
for (i = 0; i < (doc_list[idx].tm_file)->tags_array->len; ++i)
|
|
|
|
{
|
|
|
|
tag = TM_TAG((doc_list[idx].tm_file)->tags_array->pdata[i]);
|
|
|
|
if (tag == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (tag->type & tag_types)
|
|
|
|
{
|
|
|
|
if (! doc_is_utf8) utf8_name = encodings_convert_to_utf8_from_charset(tag->name,
|
|
|
|
-1, doc_list[idx].encoding, TRUE);
|
|
|
|
else utf8_name = tag->name;
|
|
|
|
if ((tag->atts.entry.scope != NULL) && isalpha(tag->atts.entry.scope[0]))
|
|
|
|
{
|
|
|
|
// context separator
|
|
|
|
gchar *cosep = (doc_list[idx].file_type->id == GEANY_FILETYPES_CPP) ? "::" : ".";
|
2006-12-06 20:44:32 +00:00
|
|
|
|
2006-11-08 11:42:05 +00:00
|
|
|
symbol = g_new0(GeanySymbol, 1);
|
|
|
|
symbol->str = g_strdup_printf("%s%s%s [%ld]", tag->atts.entry.scope, cosep,
|
|
|
|
utf8_name, tag->atts.entry.line);
|
|
|
|
symbol->type = tag->type;
|
|
|
|
symbol->line = tag->atts.entry.line;
|
|
|
|
tag_names = g_list_prepend(tag_names, symbol);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
symbol = g_new0(GeanySymbol, 1);
|
|
|
|
symbol->str = g_strdup_printf("%s [%ld]", utf8_name, tag->atts.entry.line);
|
|
|
|
symbol->type = tag->type;
|
|
|
|
symbol->line = tag->atts.entry.line;
|
|
|
|
tag_names = g_list_prepend(tag_names, symbol);
|
|
|
|
}
|
|
|
|
if (! doc_is_utf8) g_free(utf8_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tag_names = g_list_sort(tag_names, (GCompareFunc) utils_compare_symbol);
|
|
|
|
return tag_names;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GString *symbols_get_macro_list()
|
|
|
|
{
|
|
|
|
guint j, i;
|
|
|
|
const GPtrArray *tags;
|
|
|
|
GPtrArray *ftags;
|
|
|
|
GString *words;
|
|
|
|
|
|
|
|
ftags = g_ptr_array_sized_new(50);
|
|
|
|
words = g_string_sized_new(200);
|
|
|
|
|
|
|
|
for (j = 0; j < app->tm_workspace->work_objects->len; j++)
|
|
|
|
{
|
|
|
|
tags = tm_tags_extract(TM_WORK_OBJECT(app->tm_workspace->work_objects->pdata[j])->tags_array,
|
|
|
|
tm_tag_enum_t | tm_tag_variable_t | tm_tag_macro_t | tm_tag_macro_with_arg_t);
|
|
|
|
if (NULL != tags)
|
|
|
|
{
|
|
|
|
for (i = 0; ((i < tags->len) && (i < GEANY_MAX_AUTOCOMPLETE_WORDS)); ++i)
|
|
|
|
{
|
|
|
|
g_ptr_array_add(ftags, (gpointer) tags->pdata[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tm_tags_sort(ftags, NULL, FALSE);
|
|
|
|
for (j = 0; j < ftags->len; j++)
|
|
|
|
{
|
|
|
|
if (j > 0) g_string_append_c(words, ' ');
|
|
|
|
g_string_append(words, TM_TAG(ftags->pdata[j])->name);
|
|
|
|
}
|
|
|
|
g_ptr_array_free(ftags, TRUE);
|
|
|
|
return words;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static TMTag *
|
|
|
|
symbols_find_tm_tag(const GPtrArray *tags, const gchar *tag_name)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
g_return_val_if_fail(tags != NULL, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < tags->len; ++i)
|
|
|
|
{
|
2006-12-07 16:09:45 +00:00
|
|
|
if (utils_str_equal(TM_TAG(tags->pdata[i])->name, tag_name))
|
2006-11-08 11:42:05 +00:00
|
|
|
return TM_TAG(tags->pdata[i]);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TMTag *symbols_find_in_workspace(const gchar *tag_name, gint type)
|
|
|
|
{
|
|
|
|
guint j;
|
|
|
|
const GPtrArray *tags;
|
|
|
|
TMTag *tmtag;
|
|
|
|
|
|
|
|
if (app->tm_workspace->work_objects != NULL)
|
|
|
|
{
|
|
|
|
for (j = 0; j < app->tm_workspace->work_objects->len; j++)
|
|
|
|
{
|
|
|
|
tags = tm_tags_extract(
|
|
|
|
TM_WORK_OBJECT(app->tm_workspace->work_objects->pdata[j])->tags_array,
|
|
|
|
type);
|
|
|
|
if (tags == NULL) continue;
|
|
|
|
|
|
|
|
tmtag = symbols_find_tm_tag(tags, tag_name);
|
|
|
|
if (tmtag != NULL)
|
|
|
|
return tmtag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL; // not found
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-15 17:09:05 +00:00
|
|
|
gchar **symbols_get_html_entities()
|
|
|
|
{
|
|
|
|
if (html_entities == NULL)
|
|
|
|
html_tags_loaded(); // if not yet created, force creation of the array but shouldn't occur
|
|
|
|
|
|
|
|
return html_entities;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void symbols_finalize()
|
|
|
|
{
|
|
|
|
g_strfreev(html_entities);
|
|
|
|
}
|