~ubuntu-branches/ubuntu/natty/geany/natty

« back to all changes in this revision

Viewing changes to src/symbols.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2009-01-01 18:40:50 UTC
  • mfrom: (1.1.8 upstream) (3.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20090101184050-u635kualu7amyt4a
Tags: 0.15-1ubuntu1
* Merge from debian experimental, remaining change:
  - patches/20_add_debdiff_as_diff_type.dpatch: Also recognize .dpatch files
    as diff's
  - debian/geany.xpm: Replace icon with a .xpm of the new one

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *      along with this program; if not, write to the Free Software
19
19
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
 *
21
 
 * $Id: symbols.c 2458 2008-04-08 15:21:54Z eht16 $
 
21
 * $Id: symbols.c 3073 2008-10-12 17:52:22Z eht16 $
22
22
 */
23
23
 
24
24
/*
28
28
 * matching filetype is first loaded.
29
29
 */
30
30
 
 
31
#include "SciLexer.h"
31
32
#include "geany.h"
32
33
 
33
34
#include <ctype.h>
40
41
#include "filetypes.h"
41
42
#include "encodings.h"
42
43
#include "document.h"
 
44
#include "documentprivate.h"
43
45
#include "support.h"
44
46
#include "msgwindow.h"
45
47
#include "treeviews.h"
46
48
#include "main.h"
47
49
#include "navqueue.h"
48
50
#include "ui_utils.h"
 
51
#include "editor.h"
 
52
#include "sciwrappers.h"
49
53
 
50
54
 
51
55
const guint TM_GLOBAL_TYPE_MASK =
61
65
        const gchar     *tag_file;
62
66
} TagFileInfo;
63
67
 
 
68
/* Check before adding any more tags files, usually they should be downloaded separately. */
64
69
enum    /* Geany tag files */
65
70
{
66
71
        GTF_C,
68
73
        GTF_PHP,
69
74
        GTF_HTML_ENTITIES,
70
75
        GTF_LATEX,
 
76
        GTF_PYTHON,
71
77
        GTF_MAX
72
78
};
73
79
 
77
83
        {FALSE, "pascal.tags"},
78
84
        {FALSE, "php.tags"},
79
85
        {FALSE, "html_entities.tags"},
80
 
        {FALSE, "latex.tags"}
 
86
        {FALSE, "latex.tags"},
 
87
        {FALSE, "python.tags"}
81
88
};
82
89
 
83
90
static gchar *user_tags_dir;
138
145
                case GEANY_FILETYPES_PASCAL:tag_type = GTF_PASCAL; break;
139
146
                case GEANY_FILETYPES_PHP:       tag_type = GTF_PHP; break;
140
147
                case GEANY_FILETYPES_LATEX:     tag_type = GTF_LATEX; break;
 
148
                case GEANY_FILETYPES_PYTHON:tag_type = GTF_PYTHON; break;
141
149
                default:
142
150
                        return;
143
151
        }
225
233
        {
226
234
                case GEANY_FILETYPES_C: /* for C++ .h headers or C structs */
227
235
                case GEANY_FILETYPES_CPP:
 
236
                case GEANY_FILETYPES_GLSL:      /* for structs */
228
237
                /*case GEANY_FILETYPES_RUBY:*/ /* not sure what to use atm*/
229
238
                {
230
239
                        static gchar cc[] = "::";
264
273
                        tm_tag_enum_t | tm_tag_variable_t | tm_tag_macro_t | tm_tag_macro_with_arg_t);
265
274
                if (NULL != tags)
266
275
                {
267
 
                        for (i = 0; ((i < tags->len) && (i < GEANY_MAX_AUTOCOMPLETE_WORDS)); ++i)
 
276
                        for (i = 0; ((i < tags->len) && (i < editor_prefs.autocompletion_max_entries)); ++i)
268
277
                        {
269
278
                                g_ptr_array_add(ftags, (gpointer) tags->pdata[i]);
270
279
                        }
395
404
}
396
405
 
397
406
 
398
 
static const GList *get_tag_list(gint idx, guint tag_types, gint sort_mode)
 
407
static const GList *get_tag_list(GeanyDocument *doc, guint tag_types, gint sort_mode)
399
408
{
400
409
        static GList *tag_names = NULL;
401
410
 
402
 
        if (DOC_IDX_VALID(idx) && doc_list[idx].tm_file &&
403
 
                doc_list[idx].tm_file->tags_array)
 
411
        if (doc != NULL && doc->tm_file &&
 
412
                doc->tm_file->tags_array)
404
413
        {
405
414
                TMTag *tag;
406
415
                guint i;
408
417
                gboolean doc_is_utf8 = FALSE;
409
418
                gchar *utf8_name;
410
419
                const gchar *cosep =
411
 
                        symbols_get_context_separator(FILETYPE_ID(doc_list[idx].file_type));
 
420
                        symbols_get_context_separator(FILETYPE_ID(doc->file_type));
412
421
 
413
422
                if (tag_names)
414
423
                {
424
433
 
425
434
                /* encodings_convert_to_utf8_from_charset() fails with charset "None", so skip conversion
426
435
                 * for None at this point completely */
427
 
                if (utils_str_equal(doc_list[idx].encoding, "UTF-8") ||
428
 
                        utils_str_equal(doc_list[idx].encoding, "None"))
 
436
                if (utils_str_equal(doc->encoding, "UTF-8") ||
 
437
                        utils_str_equal(doc->encoding, "None"))
429
438
                        doc_is_utf8 = TRUE;
430
439
 
431
 
                for (i = 0; i < (doc_list[idx].tm_file)->tags_array->len; ++i)
 
440
                for (i = 0; i < (doc->tm_file)->tags_array->len; ++i)
432
441
                {
433
 
                        tag = TM_TAG((doc_list[idx].tm_file)->tags_array->pdata[i]);
 
442
                        tag = TM_TAG((doc->tm_file)->tags_array->pdata[i]);
434
443
                        if (tag == NULL)
435
444
                                return NULL;
436
445
 
437
446
                        if (tag->type & tag_types)
438
447
                        {
439
448
                                if (! doc_is_utf8) utf8_name = encodings_convert_to_utf8_from_charset(tag->name,
440
 
                                                                                                                        (gsize)-1, doc_list[idx].encoding, TRUE);
 
449
                                                                                                                        (gsize)-1, doc->encoding, TRUE);
441
450
                                else utf8_name = tag->name;
442
451
 
443
452
                                if (utf8_name == NULL)
557
566
}
558
567
 
559
568
 
560
 
static void init_tag_list(gint idx)
 
569
static void init_tag_list(GeanyDocument *doc)
561
570
{
562
 
        filetype_id ft_id = doc_list[idx].file_type->id;
563
 
        GtkTreeStore *tag_store = doc_list[idx].tag_store;
 
571
        filetype_id ft_id = doc->file_type->id;
 
572
        GtkTreeStore *tag_store = doc->priv->tag_store;
564
573
 
565
574
        init_tag_iters();
566
575
 
653
662
                                NULL);
654
663
                        break;
655
664
                }
 
665
/*
 
666
                case GEANY_FILETYPES_CSS:
 
667
                {
 
668
                        tag_list_add_groups(tag_store,
 
669
                                &(tv_iters.tag_class), _("Classes"), "classviewer-class",
 
670
                                &(tv_iters.tag_variable), _("ID Selectors"), "classviewer-var",
 
671
                                &(tv_iters.tag_struct), _("Type Selectors"), "classviewer-struct", NULL);
 
672
                        break;
 
673
                }
 
674
*/
656
675
                case GEANY_FILETYPES_REST:
657
676
                {
658
677
                        tag_list_add_groups(tag_store,
743
762
                                NULL);
744
763
                        break;
745
764
                }
 
765
                case GEANY_FILETYPES_F77:
746
766
                case GEANY_FILETYPES_FORTRAN:
747
767
                {
748
768
                        tag_list_add_groups(tag_store,
749
 
                                &(tv_iters.tag_namespace), _("Module"), NULL,
 
769
                                &(tv_iters.tag_namespace), _("Module"), "classviewer-class",
750
770
                                &(tv_iters.tag_struct), _("Interfaces"), "classviewer-struct",
751
771
                                &(tv_iters.tag_function), _("Functions"), "classviewer-method",
752
772
                                &(tv_iters.tag_member), _("Subroutines"), "classviewer-method",
806
826
/* the following code surely can be improved, at the moment it collects some iters
807
827
 * for removal and after that the actual removal is done. I didn't find a way to find and remove
808
828
 * an empty row in one loop (next iter fails then) */
809
 
static void hide_empty_rows(GtkTreeModel *model, GtkTreeStore *store)
 
829
static void hide_empty_rows(GtkTreeStore *store)
810
830
{
811
831
        GtkTreeIter iter, *iters[MAX_SYMBOL_TYPES] = { NULL };
812
832
        guint i = 0;
813
833
 
814
 
        if (! gtk_tree_model_get_iter_first(model, &iter))
 
834
        if (! gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
815
835
                return; /* stop when first iter is invalid, i.e. no elements */
816
836
 
817
837
        do /* first collect the iters we need to delete empty rows */
818
838
        {
819
 
                if (! gtk_tree_model_iter_has_child(model, &iter))
 
839
                if (! gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter))
820
840
                        iters[i++] = gtk_tree_iter_copy(&iter);
821
 
        } while (gtk_tree_model_iter_next(model, &iter));
 
841
        } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
822
842
 
823
843
        /* now actually delete the collected iters */
824
844
        for (i = 0; i < MAX_SYMBOL_TYPES; i++)
831
851
}
832
852
 
833
853
 
834
 
gboolean symbols_recreate_tag_list(gint idx, gint sort_mode)
 
854
gboolean symbols_recreate_tag_list(GeanyDocument *doc, gint sort_mode)
835
855
{
836
856
        GList *tmp;
837
857
        const GList *tags;
838
858
        GtkTreeIter iter;
839
 
        GtkTreeModel *model;
840
859
        static gint prev_sort_mode = SYMBOLS_SORT_BY_NAME;
841
 
        filetype_id ft_id = FILETYPE_ID(doc_list[idx].file_type);
842
 
 
843
 
        g_return_val_if_fail(DOC_IDX_VALID(idx), FALSE);
 
860
        filetype_id ft_id;
 
861
 
 
862
        g_return_val_if_fail(doc != NULL, FALSE);
 
863
 
 
864
        ft_id = FILETYPE_ID(doc->file_type);
844
865
 
845
866
        if (sort_mode == SYMBOLS_SORT_USE_PREVIOUS)
846
867
                sort_mode = prev_sort_mode;
847
868
        else
848
869
                prev_sort_mode = sort_mode;
849
870
 
850
 
        tags = get_tag_list(idx, tm_tag_max_t, sort_mode);
851
 
        if (doc_list[idx].tm_file == NULL || tags == NULL)
 
871
        tags = get_tag_list(doc, tm_tag_max_t, sort_mode);
 
872
        if (doc->tm_file == NULL || tags == NULL)
852
873
                return FALSE;
853
874
 
854
 
        gtk_tree_store_clear(doc_list[idx].tag_store);
855
 
        /* unref the store to speed up the filling(from TreeView Tutorial) */
856
 
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(doc_list[idx].tag_tree));
857
875
        /* Make sure the model stays with us after the tree view unrefs it */
858
 
        g_object_ref(model);
 
876
        g_object_ref(GTK_TREE_MODEL(doc->priv->tag_store));
859
877
        /* Detach model from view */
860
 
        gtk_tree_view_set_model(GTK_TREE_VIEW(doc_list[idx].tag_tree), NULL);
 
878
        gtk_tree_view_set_model(GTK_TREE_VIEW(doc->priv->tag_tree), NULL);
 
879
        /* Clear all contents */
 
880
        gtk_tree_store_clear(doc->priv->tag_store);
861
881
 
862
 
        init_tag_list(idx);
 
882
        init_tag_list(doc);
863
883
        for (tmp = (GList*)tags; tmp; tmp = g_list_next(tmp))
864
884
        {
865
885
                gchar buf[100];
940
960
 
941
961
                if (parent)
942
962
                {
943
 
                        gtk_tree_model_get(GTK_TREE_MODEL(doc_list[idx].tag_store), parent,
 
963
                        gtk_tree_model_get(GTK_TREE_MODEL(doc->priv->tag_store), parent,
944
964
                                           SYMBOLS_COLUMN_ICON, &icon, -1);
945
 
                        gtk_tree_store_append(doc_list[idx].tag_store, &iter, parent);
946
 
                        gtk_tree_store_set(doc_list[idx].tag_store, &iter,
 
965
                        gtk_tree_store_append(doc->priv->tag_store, &iter, parent);
 
966
                        gtk_tree_store_set(doc->priv->tag_store, &iter,
947
967
                                          SYMBOLS_COLUMN_ICON, icon,
948
968
                              SYMBOLS_COLUMN_NAME, buf,
949
969
                              SYMBOLS_COLUMN_LINE, symbol->line, -1);
952
972
                                g_object_unref(icon);
953
973
                }
954
974
        }
955
 
        hide_empty_rows(model, doc_list[idx].tag_store);
 
975
        hide_empty_rows(doc->priv->tag_store);
956
976
        /* Re-attach model to view */
957
 
        gtk_tree_view_set_model(GTK_TREE_VIEW(doc_list[idx].tag_tree), model);
958
 
        g_object_unref(model);
959
 
        gtk_tree_view_expand_all(GTK_TREE_VIEW(doc_list[idx].tag_tree));
 
977
        gtk_tree_view_set_model(GTK_TREE_VIEW(doc->priv->tag_tree),
 
978
                GTK_TREE_MODEL(doc->priv->tag_store));
 
979
        g_object_unref(GTK_TREE_MODEL(doc->priv->tag_store));
 
980
        gtk_tree_view_expand_all(GTK_TREE_VIEW(doc->priv->tag_tree));
 
981
 
960
982
        return TRUE;
961
983
}
962
984
 
963
985
 
964
986
/* Detects a global tags filetype from the *.lang.* language extension.
965
987
 * Returns NULL if there was no matching TM language. */
966
 
static filetype *detect_global_tags_filetype(const gchar *utf8_filename)
 
988
static GeanyFiletype *detect_global_tags_filetype(const gchar *utf8_filename)
967
989
{
968
990
        gchar *tags_ext;
969
991
        gchar *shortname = g_strdup(utf8_filename);
970
 
        filetype *ft = NULL;
 
992
        GeanyFiletype *ft = NULL;
971
993
 
972
994
        tags_ext = strstr(shortname, ".tags");
973
995
        if (tags_ext)
1001
1023
                char *command;
1002
1024
                const char *tags_file = argv[1];
1003
1025
                char *utf8_fname;
1004
 
                filetype *ft;
 
1026
                GeanyFiletype *ft;
1005
1027
 
1006
1028
                utf8_fname = utils_get_utf8_from_locale(tags_file);
1007
1029
                ft = detect_global_tags_filetype(utf8_fname);
1012
1034
                        g_printerr(_("Unknown filetype extension for \"%s\".\n"), tags_file);
1013
1035
                        return 1;
1014
1036
                }
 
1037
                /* load ignore list for C/C++ parser */
 
1038
                if (ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP)
 
1039
                        load_c_ignore_tags();
 
1040
 
1015
1041
                if (want_preprocess && (ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP))
1016
1042
                        command = g_strdup_printf("%s %s", pre_process, NVL(getenv("CFLAGS"), ""));
1017
1043
                else
1023
1049
                                                                                                 (const char **) (argv + 2),
1024
1050
                                                                                                 argc - 2, tags_file, ft->lang);
1025
1051
                g_free(command);
 
1052
                symbols_finalize(); /* free c_tags_ignore data */
1026
1053
                if (! status)
1027
1054
                {
1028
1055
                        g_printerr(_("Failed to create tags file, perhaps because no tags "
1047
1074
        GtkWidget *dialog;
1048
1075
        GtkFileFilter *filter;
1049
1076
 
1050
 
        dialog = gtk_file_chooser_dialog_new(_("Load Tags"), GTK_WINDOW(app->window),
 
1077
        dialog = gtk_file_chooser_dialog_new(_("Load Tags"), GTK_WINDOW(main_widgets.window),
1051
1078
                GTK_FILE_CHOOSER_ACTION_OPEN,
1052
1079
                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1053
1080
                GTK_STOCK_OPEN, GTK_RESPONSE_OK,
1067
1094
                {
1068
1095
                        gchar *fname = item->data;
1069
1096
                        gchar *utf8_fname;
1070
 
                        filetype *ft;
 
1097
                        GeanyFiletype *ft;
1071
1098
 
1072
1099
                        utf8_fname = utils_get_utf8_from_locale(fname);
1073
1100
                        ft = detect_global_tags_filetype(utf8_fname);
1097
1124
                GList *fnames;
1098
1125
                gchar *fname = node->data;
1099
1126
                gchar *utf8_fname = utils_get_utf8_from_locale(fname);
1100
 
                filetype *ft = detect_global_tags_filetype(utf8_fname);
 
1127
                GeanyFiletype *ft = detect_global_tags_filetype(utf8_fname);
1101
1128
 
1102
1129
                g_free(utf8_fname);
1103
1130
 
1104
 
                if (FILETYPE_ID(ft) < GEANY_FILETYPES_ALL)
 
1131
                if (FILETYPE_ID(ft) < GEANY_FILETYPES_NONE)
1105
1132
                {
1106
1133
                        fnames = g_hash_table_lookup(hash, ft); /* may be NULL */
1107
1134
                        fnames = g_list_append(fnames, fname);
1137
1164
 
1138
1165
static void load_user_tags(filetype_id ft_id)
1139
1166
{
1140
 
        static guchar tags_loaded[GEANY_FILETYPES_ALL] = {0};
 
1167
        static guchar tags_loaded[GEANY_FILETYPES_NONE] = {0};
1141
1168
        static GHashTable *lang_hash = NULL;
1142
1169
        GList *fnames;
1143
1170
        const GList *node;
1144
 
        const filetype *ft = filetypes[ft_id];
 
1171
        const GeanyFiletype *ft = filetypes[ft_id];
1145
1172
 
1146
 
        g_return_if_fail(ft_id < GEANY_FILETYPES_ALL);
 
1173
        g_return_if_fail(ft_id < GEANY_FILETYPES_NONE);
1147
1174
 
1148
1175
        if (tags_loaded[ft_id])
1149
1176
                return;
1160
1187
                gchar *fname;
1161
1188
 
1162
1189
                fname = g_strconcat(user_tags_dir, G_DIR_SEPARATOR_S, node->data, NULL);
1163
 
                tm_workspace_load_global_tags(fname, tm_lang);
1164
 
                geany_debug("Loaded %s (%s).", fname, ft->name);
 
1190
                if (tm_workspace_load_global_tags(fname, tm_lang))
 
1191
                {
 
1192
                        geany_debug("Loaded %s (%s), total tags: %u.", fname, ft->name,
 
1193
                                tm_get_workspace()->global_tags->len);
 
1194
                }
1165
1195
                g_free(fname);
1166
1196
        }
1167
1197
        g_list_foreach(fnames, (GFunc) g_free, NULL);
1175
1205
        const gint forward_types = tm_tag_prototype_t | tm_tag_externvar_t;
1176
1206
        gint type;
1177
1207
        TMTag *tmtag = NULL;
1178
 
        gint old_idx = document_get_cur_idx();
 
1208
        GeanyDocument *old_doc = document_get_current();
1179
1209
 
1180
1210
        /* goto tag definition: all except prototypes / forward declarations / externs */
1181
1211
        type = (definition) ? tm_tag_max_t - forward_types : forward_types;
1182
1212
 
1183
1213
        /* first look in the current document */
1184
 
        if (doc_list[old_idx].tm_file)
1185
 
                tmtag = find_work_object_tag(doc_list[old_idx].tm_file, name, type);
 
1214
        if (old_doc != NULL && old_doc->tm_file)
 
1215
                tmtag = find_work_object_tag(old_doc->tm_file, name, type);
1186
1216
 
1187
1217
        /* if not found, look in the workspace */
1188
1218
        if (tmtag == NULL)
1190
1220
 
1191
1221
        if (tmtag != NULL)
1192
1222
        {
1193
 
                gint new_idx = document_find_by_filename(
1194
 
                        tmtag->atts.entry.file->work_object.file_name, TRUE);
 
1223
                GeanyDocument *new_doc = document_find_by_real_path(
 
1224
                        tmtag->atts.entry.file->work_object.file_name);
 
1225
 
1195
1226
                /* not found in opened document, should open */
1196
 
                if (new_idx == -1)
 
1227
                if (new_doc == NULL)
1197
1228
                {
1198
 
                        new_idx = document_open_file(tmtag->atts.entry.file->work_object.file_name, FALSE, NULL, NULL);
 
1229
                        new_doc = document_open_file(tmtag->atts.entry.file->work_object.file_name, FALSE, NULL, NULL);
1199
1230
                }
1200
1231
 
1201
 
                if (navqueue_goto_line(old_idx, new_idx, tmtag->atts.entry.line))
 
1232
                if (navqueue_goto_line(old_doc, new_doc, tmtag->atts.entry.line))
1202
1233
                        return TRUE;
1203
1234
        }
1204
1235
        /* if we are here, there was no match and we are beeping ;-) */
1211
1242
}
1212
1243
 
1213
1244
 
 
1245
/* This could perhaps be improved to check for #if, class etc. */
 
1246
static gint get_function_fold_number(GeanyDocument *doc)
 
1247
{
 
1248
        /* for Java the functions are always one fold level above the class scope */
 
1249
        if (FILETYPE_ID(doc->file_type) == GEANY_FILETYPES_JAVA)
 
1250
                return SC_FOLDLEVELBASE + 1;
 
1251
        else
 
1252
                return SC_FOLDLEVELBASE;
 
1253
}
 
1254
 
 
1255
 
 
1256
/* Should be used only with symbols_get_current_function. */
 
1257
static gboolean current_function_changed(GeanyDocument *doc, gint cur_line, gint fold_level)
 
1258
{
 
1259
        static gint old_line = -2;
 
1260
        static GeanyDocument *old_doc = NULL;
 
1261
        static gint old_fold_num = -1;
 
1262
        const gint fold_num = fold_level & SC_FOLDLEVELNUMBERMASK;
 
1263
        gboolean ret;
 
1264
 
 
1265
        /* check if the cached line and file index have changed since last time: */
 
1266
        if (doc == NULL || doc != old_doc)
 
1267
                ret = TRUE;
 
1268
        else
 
1269
        if (cur_line == old_line)
 
1270
                ret = FALSE;
 
1271
        else
 
1272
        {
 
1273
                /* if the line has only changed by 1 */
 
1274
                if (abs(cur_line - old_line) == 1)
 
1275
                {
 
1276
                        const gint fn_fold =
 
1277
                                get_function_fold_number(doc);
 
1278
                        /* It's the same function if the fold number hasn't changed, or both the new
 
1279
                         * and old fold numbers are above the function fold number. */
 
1280
                        gboolean same =
 
1281
                                fold_num == old_fold_num ||
 
1282
                                (old_fold_num > fn_fold && fold_num > fn_fold);
 
1283
 
 
1284
                        ret = ! same;
 
1285
                }
 
1286
                else ret = TRUE;
 
1287
        }
 
1288
 
 
1289
        /* record current line and file index for next time */
 
1290
        old_line = cur_line;
 
1291
        old_doc = doc;
 
1292
        old_fold_num = fold_num;
 
1293
        return ret;
 
1294
}
 
1295
 
 
1296
 
 
1297
/* Parse the function name up to 2 lines before tag_line.
 
1298
 * C++ like syntax should be parsed by parse_cpp_function_at_line, otherwise the return
 
1299
 * type or argument names can be confused with the function name. */
 
1300
static gchar *parse_function_at_line(ScintillaObject *sci, gint tag_line)
 
1301
{
 
1302
        gint start, end, max_pos;
 
1303
        gchar *cur_tag;
 
1304
        gint fn_style;
 
1305
 
 
1306
        switch (sci_get_lexer(sci))
 
1307
        {
 
1308
                case SCLEX_RUBY:        fn_style = SCE_RB_DEFNAME; break;
 
1309
                case SCLEX_PYTHON:      fn_style = SCE_P_DEFNAME; break;
 
1310
                default: fn_style = SCE_C_IDENTIFIER;   /* several lexers use SCE_C_IDENTIFIER */
 
1311
        }
 
1312
        start = sci_get_position_from_line(sci, tag_line - 2);
 
1313
        max_pos = sci_get_position_from_line(sci, tag_line + 1);
 
1314
        while (sci_get_style_at(sci, start) != fn_style
 
1315
                && start < max_pos) start++;
 
1316
 
 
1317
        end = start;
 
1318
        while (sci_get_style_at(sci, end) == fn_style
 
1319
                && end < max_pos) end++;
 
1320
 
 
1321
        if (start == end) return NULL;
 
1322
        cur_tag = g_malloc(end - start + 1);
 
1323
        sci_get_text_range(sci, start, end, cur_tag);
 
1324
        return cur_tag;
 
1325
}
 
1326
 
 
1327
 
 
1328
/* Parse the function name */
 
1329
static gchar *parse_cpp_function_at_line(ScintillaObject *sci, gint tag_line)
 
1330
{
 
1331
        gint start, end, first_pos, max_pos;
 
1332
        gint tmp;
 
1333
        gchar c;
 
1334
        gchar *cur_tag;
 
1335
 
 
1336
        first_pos = end = sci_get_position_from_line(sci, tag_line);
 
1337
        max_pos = sci_get_position_from_line(sci, tag_line + 1);
 
1338
        tmp = 0;
 
1339
        /* goto the begin of function body */
 
1340
        while (end < max_pos &&
 
1341
                (tmp = sci_get_char_at(sci, end)) != '{' &&
 
1342
                tmp != 0) end++;
 
1343
        if (tmp == 0) end --;
 
1344
 
 
1345
        /* go back to the end of function identifier */
 
1346
        while (end > 0 && end > first_pos - 500 &&
 
1347
                (tmp = sci_get_char_at(sci, end)) != '(' &&
 
1348
                tmp != 0) end--;
 
1349
        end--;
 
1350
        if (end < 0) end = 0;
 
1351
 
 
1352
        /* skip whitespaces between identifier and ( */
 
1353
        while (end > 0 && isspace(sci_get_char_at(sci, end))) end--;
 
1354
 
 
1355
        start = end;
 
1356
        c = 0;
 
1357
        /* Use tmp to find SCE_C_IDENTIFIER or SCE_C_GLOBALCLASS chars */
 
1358
        while (start >= 0 && ((tmp = sci_get_style_at(sci, start)) == SCE_C_IDENTIFIER
 
1359
                 ||  tmp == SCE_C_GLOBALCLASS
 
1360
                 || (c = sci_get_char_at(sci, start)) == '~'
 
1361
                 ||  c == ':'))
 
1362
                start--;
 
1363
        if (start != 0 && start < end) start++; /* correct for last non-matching char */
 
1364
 
 
1365
        if (start == end) return NULL;
 
1366
        cur_tag = g_malloc(end - start + 2);
 
1367
        sci_get_text_range(sci, start, end + 1, cur_tag);
 
1368
        return cur_tag;
 
1369
}
 
1370
 
 
1371
 
 
1372
/* Sets *tagname to point at the current function or tag name.
 
1373
 * If doc is NULL, reset the cached current tag data to ensure it will be reparsed on the next
 
1374
 * call to this function.
 
1375
 * Returns: line number of the current tag, or -1 if unknown. */
 
1376
gint symbols_get_current_function(GeanyDocument *doc, const gchar **tagname)
 
1377
{
 
1378
        static gint tag_line = -1;
 
1379
        static gchar *cur_tag = NULL;
 
1380
        gint line;
 
1381
        gint fold_level;
 
1382
        TMWorkObject *tm_file;
 
1383
 
 
1384
        if (doc == NULL)        /* reset current function */
 
1385
        {
 
1386
                current_function_changed(NULL, -1, -1);
 
1387
                g_free(cur_tag);
 
1388
                cur_tag = g_strdup(_("unknown"));
 
1389
                if (tagname != NULL)
 
1390
                        *tagname = cur_tag;
 
1391
                tag_line = -1;
 
1392
                return tag_line;
 
1393
        }
 
1394
 
 
1395
        line = sci_get_current_line(doc->editor->sci);
 
1396
        fold_level = sci_get_fold_level(doc->editor->sci, line);
 
1397
        /* check if the cached line and file index have changed since last time: */
 
1398
        if (! current_function_changed(doc, line, fold_level))
 
1399
        {
 
1400
                /* we can assume same current function as before */
 
1401
                *tagname = cur_tag;
 
1402
                return tag_line;
 
1403
        }
 
1404
        g_free(cur_tag); /* free the old tag, it will be replaced. */
 
1405
 
 
1406
        /* if line is at base fold level, we're not in a function */
 
1407
        if ((fold_level & SC_FOLDLEVELNUMBERMASK) == SC_FOLDLEVELBASE)
 
1408
        {
 
1409
                cur_tag = g_strdup(_("unknown"));
 
1410
                *tagname = cur_tag;
 
1411
                tag_line = -1;
 
1412
                return tag_line;
 
1413
        }
 
1414
        tm_file = doc->tm_file;
 
1415
 
 
1416
        /* if the document has no changes, get the previous function name from TM */
 
1417
        if(! doc->changed && tm_file != NULL && tm_file->tags_array != NULL)
 
1418
        {
 
1419
                const TMTag *tag = (const TMTag*) tm_get_current_function(tm_file->tags_array, line);
 
1420
 
 
1421
                if (tag != NULL)
 
1422
                {
 
1423
                        gchar *tmp;
 
1424
                        tmp = tag->atts.entry.scope;
 
1425
                        cur_tag = tmp ? g_strconcat(tmp, "::", tag->name, NULL) : g_strdup(tag->name);
 
1426
                        *tagname = cur_tag;
 
1427
                        tag_line = tag->atts.entry.line;
 
1428
                        return tag_line;
 
1429
                }
 
1430
        }
 
1431
 
 
1432
        /* parse the current function name here because TM line numbers may have changed,
 
1433
         * and it would take too long to reparse the whole file. */
 
1434
        if (doc->file_type != NULL && doc->file_type->id != GEANY_FILETYPES_NONE)
 
1435
        {
 
1436
                const gint fn_fold = get_function_fold_number(doc);
 
1437
 
 
1438
                tag_line = line;
 
1439
                do      /* find the top level fold point */
 
1440
                {
 
1441
                        tag_line = sci_get_fold_parent(doc->editor->sci, tag_line);
 
1442
                        fold_level = sci_get_fold_level(doc->editor->sci, tag_line);
 
1443
                } while (tag_line >= 0 &&
 
1444
                        (fold_level & SC_FOLDLEVELNUMBERMASK) != fn_fold);
 
1445
 
 
1446
                if (tag_line >= 0)
 
1447
                {
 
1448
                        if (sci_get_lexer(doc->editor->sci) == SCLEX_CPP)
 
1449
                                cur_tag = parse_cpp_function_at_line(doc->editor->sci, tag_line);
 
1450
                        else
 
1451
                                cur_tag = parse_function_at_line(doc->editor->sci, tag_line);
 
1452
 
 
1453
                        if (cur_tag != NULL)
 
1454
                        {
 
1455
                                *tagname = cur_tag;
 
1456
                                return tag_line;
 
1457
                        }
 
1458
                }
 
1459
        }
 
1460
 
 
1461
        cur_tag = g_strdup(_("unknown"));
 
1462
        *tagname = cur_tag;
 
1463
        tag_line = -1;
 
1464
        return tag_line;
 
1465
}
 
1466
 
 
1467