~ubuntu-branches/ubuntu/raring/geany/raring-proposed

« back to all changes in this revision

Viewing changes to tagmanager/tm_workspace.c

  • Committer: Bazaar Package Importer
  • Author(s): Damián Viano
  • Date: 2008-05-02 11:37:45 UTC
  • mto: (3.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20080502113745-7q62rqhl2ku02ptu
Import upstream version 0.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#ifdef HAVE_GLOB_H
20
20
# include <glob.h>
21
21
#endif
22
 
// handling of P_tmpdir, should be something like /tmp, take the root directory under Win32,
23
 
// and assume /tmp on non-Win32 systems where P_tmpdir is not set
24
 
#ifndef P_tmpdir
25
 
# ifdef G_OS_WIN32
26
 
#  define P_tmpdir "\\"
27
 
# else
28
 
#  define P_tmpdir "/tmp"
29
 
# endif
30
 
#endif
 
22
#include <glib/gstdio.h>
31
23
 
32
24
#include "tm_tag.h"
33
25
#include "tm_workspace.h"
34
26
#include "tm_project.h"
35
27
 
 
28
 
36
29
static TMWorkspace *theWorkspace = NULL;
37
30
guint workspace_class_id = 0;
38
31
 
39
32
static gboolean tm_create_workspace(void)
40
33
{
41
 
#ifdef G_OS_WIN32
42
 
        char *file_name = g_strdup_printf("%s_%s_%ld.%d", P_tmpdir, PACKAGE, time(NULL), getpid());
43
 
#else
44
 
        char *file_name = g_strdup_printf("%s/%s_%ld.%d", P_tmpdir, PACKAGE, time(NULL), getpid());
45
 
#endif
46
 
 
47
34
        workspace_class_id = tm_work_object_register(tm_workspace_free, tm_workspace_update
48
35
                  , tm_workspace_find_object);
49
36
        theWorkspace = g_new(TMWorkspace, 1);
50
37
        if (FALSE == tm_work_object_init(TM_WORK_OBJECT(theWorkspace),
51
 
                  workspace_class_id, file_name, TRUE))
 
38
                  workspace_class_id, NULL, TRUE))
52
39
        {
53
 
                g_free(file_name);
54
40
                g_free(theWorkspace);
55
41
                theWorkspace = NULL;
56
42
                g_warning("Failed to initialize workspace");
57
43
                return FALSE;
58
44
        }
59
45
 
60
 
        g_free(file_name);
61
46
        theWorkspace->global_tags = NULL;
62
47
        theWorkspace->work_objects = NULL;
63
48
        return TRUE;
88
73
                                tm_tag_free(theWorkspace->global_tags->pdata[i]);
89
74
                        g_ptr_array_free(theWorkspace->global_tags, TRUE);
90
75
                }
91
 
                unlink(theWorkspace->work_object.file_name);
92
76
                tm_work_object_destroy(TM_WORK_OBJECT(theWorkspace));
93
77
                g_free(theWorkspace);
94
78
                theWorkspace = NULL;
95
79
        }
96
80
}
97
81
 
98
 
const TMWorkspace *tm_get_workspace(void)
 
82
const TMWorkspace *tm_get_workspace()
99
83
{
100
84
        if (NULL == theWorkspace)
101
85
                tm_create_workspace();
104
88
 
105
89
gboolean tm_workspace_add_object(TMWorkObject *work_object)
106
90
{
 
91
        /* theWorkspace should already have been created otherwise something went wrong */
107
92
        if (NULL == theWorkspace)
108
 
                tm_create_workspace();
 
93
                return FALSE;
109
94
        if (NULL == theWorkspace->work_objects)
110
95
                theWorkspace->work_objects = g_ptr_array_new();
111
96
        g_ptr_array_add(theWorkspace->work_objects, work_object);
113
98
        return TRUE;
114
99
}
115
100
 
116
 
gboolean tm_workspace_remove_object(TMWorkObject *w, gboolean free)
 
101
gboolean tm_workspace_remove_object(TMWorkObject *w, gboolean do_free, gboolean update)
117
102
{
118
103
        guint i;
119
104
        if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects)
120
105
                  || (NULL == w))
121
106
                return FALSE;
 
107
 
 
108
 
122
109
        for (i=0; i < theWorkspace->work_objects->len; ++i)
123
110
        {
124
111
                if (theWorkspace->work_objects->pdata[i] == w)
125
112
                {
126
 
                        if (free)
 
113
                        if (do_free)
127
114
                                tm_work_object_free(w);
128
115
                        g_ptr_array_remove_index_fast(theWorkspace->work_objects, i);
129
 
                        tm_workspace_update(TM_WORK_OBJECT(theWorkspace), TRUE, FALSE, FALSE);
 
116
                        if (update)
 
117
                                tm_workspace_update(TM_WORK_OBJECT(theWorkspace), TRUE, FALSE, FALSE);
130
118
                        return TRUE;
131
119
                }
132
120
        }
 
121
 
133
122
        return FALSE;
134
123
}
135
124
 
 
125
static TMTagAttrType global_tags_sort_attrs[] =
 
126
{
 
127
        tm_tag_attr_name_t, tm_tag_attr_scope_t,
 
128
        tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0
 
129
};
 
130
 
136
131
gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode)
137
132
{
138
133
        FILE *fp;
139
134
        TMTag *tag;
140
 
        TMTagAttrType attr[] = { tm_tag_attr_name_t, 0 };
141
135
 
142
 
        if (NULL == (fp = fopen(tags_file, "r")))
 
136
        if (NULL == (fp = g_fopen(tags_file, "r")))
143
137
                return FALSE;
144
138
        if (NULL == theWorkspace)
145
 
                tm_create_workspace();
 
139
                return FALSE;
146
140
        if (NULL == theWorkspace->global_tags)
147
141
                theWorkspace->global_tags = g_ptr_array_new();
148
142
        while (NULL != (tag = tm_tag_new_from_file(NULL, fp, mode)))
149
143
                g_ptr_array_add(theWorkspace->global_tags, tag);
150
144
        fclose(fp);
151
145
 
152
 
        // resort the whole array, because tm_tags_find expects a sorted array and it is not sorted
153
 
        // when global.tags, php.tags and latex.tags are loaded at the same time
154
 
        tm_tags_sort(theWorkspace->global_tags, attr, TRUE);
 
146
        /* resort the whole array, because tm_tags_find expects a sorted array and it is not sorted
 
147
         * when global.tags, php.tags and latex.tags are loaded at the same time */
 
148
        tm_tags_sort(theWorkspace->global_tags, global_tags_sort_attrs, TRUE);
155
149
 
156
150
        return TRUE;
157
151
}
158
152
 
159
 
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
160
 
  , int includes_count, const char *tags_file)
 
153
static guint tm_file_inode_hash(gconstpointer key)
 
154
{
 
155
        struct stat file_stat;
 
156
        const char *filename = (const char*)key;
 
157
        if (g_stat(filename, &file_stat) == 0)
 
158
        {
 
159
#ifdef TM_DEBUG
 
160
                g_message ("Hash for '%s' is '%d'\n", filename, file_stat.st_ino);
 
161
#endif
 
162
                return g_direct_hash (GUINT_TO_POINTER (file_stat.st_ino));
 
163
        } else {
 
164
                return 0;
 
165
        }
 
166
}
 
167
 
 
168
static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer user_data)
 
169
{
 
170
        GList **pp_list = (GList**)user_data;
 
171
 
 
172
        if (user_data == NULL)
 
173
                return;
 
174
 
 
175
        *pp_list = g_list_prepend(*pp_list, value);
 
176
}
 
177
 
 
178
static void write_includes_file(FILE *fp, GList *includes_files)
 
179
{
 
180
        GList *node;
 
181
 
 
182
        node = includes_files;
 
183
        while (node)
 
184
        {
 
185
                char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
 
186
                int str_len = strlen(str);
 
187
 
 
188
                fwrite(str, str_len, 1, fp);
 
189
                free(str);
 
190
                node = g_list_next (node);
 
191
        }
 
192
}
 
193
 
 
194
 
 
195
static void append_to_temp_file(FILE *fp, GList *file_list)
 
196
{
 
197
        GList *node;
 
198
 
 
199
        node = file_list;
 
200
        while (node)
 
201
        {
 
202
                const char *fname = node->data;
 
203
                char *contents;
 
204
                size_t length;
 
205
                GError *err = NULL;
 
206
 
 
207
                if (! g_file_get_contents(fname, &contents, &length, &err))
 
208
                {
 
209
                        fprintf(stderr, "Unable to read file: %s\n", err->message);
 
210
                        g_error_free(err);
 
211
                }
 
212
                else
 
213
                {
 
214
                        fwrite(contents, length, 1, fp);
 
215
                        fwrite("\n", 1, 1, fp); /* in case file doesn't end in newline (e.g. windows). */
 
216
                        g_free(contents);
 
217
                }
 
218
                node = g_list_next (node);
 
219
        }
 
220
}
 
221
 
 
222
static gint get_global_tag_type_mask(gint lang)
 
223
{
 
224
        switch (lang)
 
225
        {
 
226
                case 0:
 
227
                case 1:
 
228
                        /* C/C++ */
 
229
                        return tm_tag_class_t | tm_tag_typedef_t | tm_tag_enum_t | tm_tag_enumerator_t |
 
230
                                tm_tag_prototype_t |
 
231
                                tm_tag_function_t | tm_tag_method_t |   /* for inline functions */
 
232
                                tm_tag_macro_t | tm_tag_macro_with_arg_t;
 
233
                default:
 
234
                        return tm_tag_max_t;
 
235
        }
 
236
}
 
237
 
 
238
gboolean tm_workspace_create_global_tags(const char *config_dir, const char *pre_process,
 
239
        const char **includes, int includes_count, const char *tags_file, int lang)
161
240
{
162
241
#ifdef HAVE_GLOB_H
163
242
        glob_t globbuf;
169
248
        FILE *fp;
170
249
        TMWorkObject *source_file;
171
250
        GPtrArray *tags_array;
 
251
        GHashTable *includes_files_hash;
172
252
        GList *includes_files = NULL;
173
 
        guint list_len;
174
 
        guint idx_main;
175
 
        guint idx_sub;
176
 
        int remove_count = 0;
177
253
#ifdef G_OS_WIN32
178
 
        char *temp_file = g_strdup_printf("%s_%d_%ld_1.cpp", P_tmpdir, getpid(), time(NULL));
179
 
        char *temp_file2 = g_strdup_printf("%s_%d_%ld_2.cpp", P_tmpdir, getpid(), time(NULL));
 
254
        char *temp_file = g_strdup_printf("%s\\_%d_%ld_1.cpp", config_dir, getpid(), time(NULL));
 
255
        char *temp_file2 = g_strdup_printf("%s\\_%d_%ld_2.cpp", config_dir, getpid(), time(NULL));
180
256
#else
181
 
        char *temp_file = g_strdup_printf("%s/%d_%ld_1.cpp", P_tmpdir, getpid(), time(NULL));
182
 
        char *temp_file2 = g_strdup_printf("%s/%d_%ld_2.cpp", P_tmpdir, getpid(), time(NULL));
 
257
        char *temp_file = g_strdup_printf("%s/%d_%ld_1.cpp", config_dir, getpid(), time(NULL));
 
258
        char *temp_file2 = g_strdup_printf("%s/%d_%ld_2.cpp", config_dir, getpid(), time(NULL));
183
259
#endif
184
 
        TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_scope_t
185
 
                , tm_tag_attr_type_t, 0};
186
 
        if (NULL == (fp = fopen(temp_file, "w")))
 
260
 
 
261
        if (NULL == theWorkspace || NULL == (fp = g_fopen(temp_file, "w")))
187
262
                return FALSE;
188
263
 
 
264
        includes_files_hash = g_hash_table_new_full (tm_file_inode_hash,
 
265
                                                                                                 g_direct_equal,
 
266
                                                                                                 NULL, g_free);
 
267
 
189
268
#ifdef HAVE_GLOB_H
190
269
        globbuf.gl_offs = 0;
 
270
 
 
271
        if (includes[0][0] == '"')      /* leading \" char for glob matching */
191
272
        for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
192
273
        {
193
274
                int dirty_len = strlen(includes[idx_inc]);
194
 
                char *clean_path = malloc(dirty_len - 1);
 
275
                char *clean_path = g_malloc(dirty_len - 1);
195
276
                strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1);
196
277
                clean_path[dirty_len - 2] = 0;
197
278
 
198
 
                //printf("[o][%s]\n", clean_path);
 
279
#ifdef TM_DEBUG
 
280
                g_message ("[o][%s]\n", clean_path);
 
281
#endif
199
282
                glob(clean_path, 0, NULL, &globbuf);
200
 
                //printf("matches: %d\n", globbuf.gl_pathc);
 
283
 
 
284
#ifdef TM_DEBUG
 
285
                g_message ("matches: %d\n", globbuf.gl_pathc);
 
286
#endif
 
287
 
201
288
                for(idx_glob = 0; idx_glob < globbuf.gl_pathc; idx_glob++)
202
289
                {
203
 
                        includes_files = g_list_append(includes_files, strdup(globbuf.gl_pathv[idx_glob]));
204
 
                        //printf(">>> %s\n", globbuf.gl_pathv[idx_glob]);
 
290
#ifdef TM_DEBUG
 
291
                        g_message (">>> %s\n", globbuf.gl_pathv[idx_glob]);
 
292
#endif
 
293
                        if (!g_hash_table_lookup(includes_files_hash,
 
294
                                                                        globbuf.gl_pathv[idx_glob]))
 
295
                        {
 
296
                                char* file_name_copy = strdup(globbuf.gl_pathv[idx_glob]);
 
297
                                g_hash_table_insert(includes_files_hash, file_name_copy,
 
298
                                                                        file_name_copy);
 
299
#ifdef TM_DEBUG
 
300
                                g_message ("Added ...\n");
 
301
#endif
 
302
                        }
205
303
                }
206
304
                globfree(&globbuf);
207
305
                free(clean_path);
208
306
        }
209
 
#else
 
307
        else
 
308
#endif
 
309
        /* no glob support or globbing not wanted */
210
310
        for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
211
311
        {
212
 
                includes_files = g_list_append(includes_files, strdup(includes[idx_inc]));
 
312
                if (!g_hash_table_lookup(includes_files_hash,
 
313
                                                                        includes[idx_inc]))
 
314
                {
 
315
                        char* file_name_copy = strdup(includes[idx_inc]);
 
316
                        g_hash_table_insert(includes_files_hash, file_name_copy,
 
317
                                                                file_name_copy);
 
318
                }
213
319
        }
214
 
#endif
215
 
 
216
320
 
217
321
        /* Checks for duplicate file entries which would case trouble */
218
 
        {
219
 
                struct stat main_stat;
220
 
                struct stat sub_stat;
221
 
 
222
 
                remove_count = 0;
223
 
 
224
 
                list_len = g_list_length(includes_files);
225
 
 
226
 
                /* We look for files with the same inode */
227
 
                for(idx_main = 0; idx_main < list_len; idx_main++)
228
 
                {
229
 
//                      printf("%d / %d\n", idx_main, list_len - 1);
230
 
                        stat(g_list_nth_data(includes_files, idx_main), &main_stat);
231
 
                        for(idx_sub = idx_main + 1; idx_sub < list_len; idx_sub++)
232
 
                        {
233
 
                                GList *element = NULL;
234
 
 
235
 
                                stat(g_list_nth_data(includes_files, idx_sub), &sub_stat);
236
 
 
237
 
 
238
 
                                if(main_stat.st_ino != sub_stat.st_ino)
239
 
                                        continue;
240
 
 
241
 
                                /* Inodes match */
242
 
 
243
 
                                element = g_list_nth(includes_files, idx_sub);
244
 
 
245
 
/*                              printf("%s == %s\n", g_list_nth_data(includes_files, idx_main),
246
 
                                                                                 g_list_nth_data(includes_files, idx_sub)); */
247
 
 
248
 
                                /* We delete the duplicate entry from the list */
249
 
                                includes_files = g_list_remove_link(includes_files, element);
250
 
                                remove_count++;
251
 
 
252
 
                                /* Don't forget to free the mallocs (we duplicated every string earlier!) */
253
 
                                free(element->data);
254
 
 
255
 
                                idx_sub--; /* Cause the inner loop not to move; good since we removed
256
 
                                                           an element at the current position; we don't have to worry
257
 
                                                           about the outer loop because the inner loop always starts
258
 
                                                           after the outer loop's index */
259
 
 
260
 
                                list_len = g_list_length(includes_files);
261
 
                        }
262
 
                }
263
 
        }
264
 
 
265
 
 
266
 
        printf("writing out files to %s\n", temp_file);
267
 
        for(idx_main = 0; idx_main < g_list_length(includes_files); idx_main++)
268
 
        {
269
 
                char *str = g_strdup_printf("#include \"%s\"\n",
270
 
                                                                        (char*)g_list_nth_data(includes_files,
271
 
                                                                                                                   idx_main));
272
 
                int str_len = strlen(str);
273
 
 
274
 
                fwrite(str, str_len, 1, fp);
275
 
 
276
 
                free(str);
277
 
                free(g_list_nth(includes_files, idx_main) -> data);
278
 
        }
279
 
 
 
322
        g_hash_table_foreach(includes_files_hash, tm_move_entries_to_g_list,
 
323
                                                 &includes_files);
 
324
 
 
325
        includes_files = g_list_reverse (includes_files);
 
326
 
 
327
#ifdef TM_DEBUG
 
328
        g_message ("writing out files to %s\n", temp_file);
 
329
#endif
 
330
        if (pre_process != NULL)
 
331
                write_includes_file(fp, includes_files);
 
332
        else
 
333
                append_to_temp_file(fp, includes_files);
 
334
 
 
335
        g_list_free (includes_files);
 
336
        g_hash_table_destroy(includes_files_hash);
 
337
        includes_files_hash = NULL;
 
338
        includes_files = NULL;
280
339
        fclose(fp);
281
340
 
282
 
        command = g_strdup_printf("%s %s >%s", pre_process, temp_file, temp_file2);
283
 
        system(command);
284
 
        g_free(command);
285
 
        unlink(temp_file);
286
 
        g_free(temp_file);
287
 
        source_file = tm_source_file_new(temp_file2, TRUE, NULL);
 
341
        /* FIXME: The following grep command removes the lines
 
342
         * G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
 
343
         * that in tagmanager, the files are not correctly parsed and the typedefs
 
344
         * following these lines are incorrectly parsed. The real fix should,
 
345
         * of course be in tagmanager (c) parser. This is just a temporary fix.
 
346
         */
 
347
        if (pre_process != NULL)
 
348
        {
 
349
                command = g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
 
350
                                                          pre_process, temp_file, temp_file2);
 
351
#ifdef TM_DEBUG
 
352
                g_message("Executing: %s", command);
 
353
#endif
 
354
                system(command);
 
355
                g_free(command);
 
356
                g_unlink(temp_file);
 
357
                g_free(temp_file);
 
358
        }
 
359
        else
 
360
        {
 
361
                /* no pre-processing needed, so temp_file2 = temp_file */
 
362
                g_free(temp_file2);
 
363
                temp_file2 = temp_file;
 
364
                temp_file = NULL;
 
365
        }
 
366
        source_file = tm_source_file_new(temp_file2, TRUE, tm_source_file_get_lang_name(lang));
288
367
        if (NULL == source_file)
289
368
        {
290
 
                unlink(temp_file2);
 
369
                g_unlink(temp_file2);
291
370
                return FALSE;
292
371
        }
293
 
        unlink(temp_file2);
 
372
        g_unlink(temp_file2);
294
373
        g_free(temp_file2);
295
374
        if ((NULL == source_file->tags_array) || (0 == source_file->tags_array->len))
296
375
        {
297
376
                tm_source_file_free(source_file);
298
377
                return FALSE;
299
378
        }
300
 
        tags_array = tm_tags_extract(source_file->tags_array, tm_tag_class_t |
301
 
          tm_tag_typedef_t | tm_tag_prototype_t | tm_tag_enum_t | tm_tag_macro_with_arg_t);
 
379
        tags_array = tm_tags_extract(source_file->tags_array, get_global_tag_type_mask(lang));
302
380
        if ((NULL == tags_array) || (0 == tags_array->len))
303
381
        {
304
382
                if (tags_array)
306
384
                tm_source_file_free(source_file);
307
385
                return FALSE;
308
386
        }
309
 
        if (FALSE == tm_tags_sort(tags_array, sort_attrs, TRUE))
310
 
        {
311
 
                tm_source_file_free(source_file);
312
 
                return FALSE;
313
 
        }
314
 
        if (NULL == (fp = fopen(tags_file, "w")))
315
 
        {
316
 
                tm_source_file_free(source_file);
317
 
                return FALSE;
318
 
        }
319
 
        for (i=0; i < tags_array->len; ++i)
 
387
        if (FALSE == tm_tags_sort(tags_array, global_tags_sort_attrs, TRUE))
 
388
        {
 
389
                tm_source_file_free(source_file);
 
390
                return FALSE;
 
391
        }
 
392
        if (NULL == (fp = g_fopen(tags_file, "w")))
 
393
        {
 
394
                tm_source_file_free(source_file);
 
395
                return FALSE;
 
396
        }
 
397
        for (i = 0; i < tags_array->len; ++i)
320
398
        {
321
399
                tm_tag_write(TM_TAG(tags_array->pdata[i]), fp, tm_tag_attr_type_t
322
 
                  | tm_tag_attr_scope_t | tm_tag_attr_arglist_t | tm_tag_attr_vartype_t);
 
400
                  | tm_tag_attr_scope_t | tm_tag_attr_arglist_t | tm_tag_attr_vartype_t
 
401
                  | tm_tag_attr_pointer_t);
323
402
        }
324
403
        fclose(fp);
325
404
        tm_source_file_free(source_file);
352
431
        guint i, j;
353
432
        TMWorkObject *w;
354
433
        TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t
355
 
                , tm_tag_attr_scope_t, tm_tag_attr_type_t, 0};
 
434
                , tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0};
356
435
 
357
436
#ifdef TM_DEBUG
358
437
        g_message("Recreating workspace tags array");
461
540
        matches[0] = tm_tags_find(theWorkspace->work_object.tags_array, name, partial, &tagCount[0]);
462
541
        matches[1] = tm_tags_find(theWorkspace->global_tags, name, partial, &tagCount[1]);
463
542
 
464
 
        // file tags
 
543
        /* file tags */
465
544
        if (matches[0] && *matches[0])
466
545
        {
467
 
                // tag->atts.file.lang contains the line of the tag and
468
 
                // tags->atts.entry.file->lang contains the language
 
546
                /* tag->atts.file.lang contains the line of the tag and
 
547
                 * tags->atts.entry.file->lang contains the language */
469
548
                tags_lang = (*matches[0])->atts.entry.file->lang;
470
549
 
471
550
                for (tagIter=0;tagIter<tagCount[0];++tagIter)
486
565
                }
487
566
        }
488
567
 
489
 
        // global tags
 
568
        /* global tags */
490
569
        if (matches[1] && *matches[1])
491
570
        {
492
571
                int tags_lang_alt = 0;
493
 
                // tag->atts.file.lang contains the language and
494
 
                // tags->atts.entry.file is NULL
 
572
                /* tag->atts.file.lang contains the language and
 
573
                 * tags->atts.entry.file is NULL */
495
574
                tags_lang = (*matches[1])->atts.file.lang;
496
 
                // tags_lang_alt is used to load C global tags only once for C and C++
497
 
                // lang = 1 is C++, lang = 0 is C
498
 
                // if we have lang 0, than accept also lang 1 for C++
499
 
                if (tags_lang == 0)     // C or C++
 
575
                /* tags_lang_alt is used to load C global tags only once for C and C++
 
576
                 * lang = 1 is C++, lang = 0 is C
 
577
                 * if we have lang 0, than accept also lang 1 for C++ */
 
578
                if (tags_lang == 0)     /* C or C++ */
500
579
                        tags_lang_alt = 1;
501
580
                else
502
 
                        tags_lang_alt = tags_lang; // otherwise just ignore it
 
581
                        tags_lang_alt = tags_lang; /* otherwise just ignore it */
503
582
 
504
583
                for (tagIter=0;tagIter<tagCount[1];++tagIter)
505
584
                {
521
600
                }
522
601
        }
523
602
 
524
 
        tm_tags_sort(tags, attrs, TRUE);
525
 
        return tags;
 
603
        if (attrs)
 
604
                tm_tags_sort(tags, attrs, TRUE);
 
605
        return tags;
 
606
}
 
607
 
 
608
static gboolean match_langs(gint lang, const TMTag *tag)
 
609
{
 
610
        if (tag->atts.entry.file)
 
611
        {       /* workspace tag */
 
612
                if (lang == tag->atts.entry.file->lang)
 
613
                        return TRUE;
 
614
        }
 
615
        else
 
616
        {       /* global tag */
 
617
                if (lang == tag->atts.file.lang)
 
618
                        return TRUE;
 
619
        }
 
620
        return FALSE;
 
621
}
 
622
 
 
623
/* scope can be NULL.
 
624
 * lang can be -1 */
 
625
static int
 
626
fill_find_tags_array (GPtrArray *dst, const GPtrArray *src,
 
627
                                          const char *name, const char *scope, int type, gboolean partial,
 
628
                                          gint lang, gboolean first)
 
629
{
 
630
        TMTag **match;
 
631
        int tagIter, count;
 
632
 
 
633
        if ((!src) || (!dst) || (!name) || (!*name))
 
634
                return 0;
 
635
 
 
636
        match = tm_tags_find (src, name, partial, &count);
 
637
        if (count && match && *match)
 
638
        {
 
639
                for (tagIter = 0; tagIter < count; ++tagIter)
 
640
                {
 
641
                        if (! scope || (match[tagIter]->atts.entry.scope &&
 
642
                                0 == strcmp(match[tagIter]->atts.entry.scope, scope)))
 
643
                        {
 
644
                                if (type & match[tagIter]->type)
 
645
                                if (lang == -1 || match_langs(lang, match[tagIter]))
 
646
                                {
 
647
                                        g_ptr_array_add (dst, match[tagIter]);
 
648
                                        if (first)
 
649
                                                break;
 
650
                                }
 
651
                        }
 
652
                }
 
653
        }
 
654
        return dst->len;
 
655
}
 
656
 
 
657
 
 
658
/* adapted from tm_workspace_find, Anjuta 2.02 */
 
659
const GPtrArray *
 
660
tm_workspace_find_scoped (const char *name, const char *scope, gint type,
 
661
                TMTagAttrType *attrs, gboolean partial, langType lang, gboolean global_search)
 
662
{
 
663
        static GPtrArray *tags = NULL;
 
664
 
 
665
        if ((!theWorkspace))
 
666
                return NULL;
 
667
 
 
668
        if (tags)
 
669
                g_ptr_array_set_size (tags, 0);
 
670
        else
 
671
                tags = g_ptr_array_new ();
 
672
 
 
673
        fill_find_tags_array (tags, theWorkspace->work_object.tags_array,
 
674
                                                  name, scope, type, partial, lang, FALSE);
 
675
        if (global_search)
 
676
        {
 
677
                /* for a scoped tag, I think we always want the same language */
 
678
                fill_find_tags_array (tags, theWorkspace->global_tags,
 
679
                                                          name, scope, type, partial, lang, FALSE);
 
680
        }
 
681
        if (attrs)
 
682
                tm_tags_sort (tags, attrs, TRUE);
 
683
        return tags;
 
684
}
 
685
 
 
686
 
 
687
const TMTag *
 
688
tm_get_current_function (GPtrArray * file_tags, const gulong line)
 
689
{
 
690
        GPtrArray *const local = tm_tags_extract (file_tags, tm_tag_function_t);
 
691
        if (local && local->len)
 
692
        {
 
693
                guint i;
 
694
                TMTag *tag, *function_tag = NULL;
 
695
                gulong function_line = 0;
 
696
                glong delta;
 
697
 
 
698
                for (i = 0; (i < local->len); ++i)
 
699
                {
 
700
                        tag = TM_TAG (local->pdata[i]);
 
701
                        delta = line - tag->atts.entry.line;
 
702
                        if (delta >= 0 && (gulong)delta < line - function_line)
 
703
                        {
 
704
                                function_tag = tag;
 
705
                                function_line = tag->atts.entry.line;
 
706
                        }
 
707
                }
 
708
                g_ptr_array_free (local, TRUE);
 
709
                return function_tag;
 
710
        }
 
711
        return NULL;
526
712
}
527
713
 
528
714