~ubuntu-branches/ubuntu/utopic/geany/utopic

« back to all changes in this revision

Viewing changes to .pc/git_build_with_latest_glib.patch/tagmanager/tm_workspace.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-04-19 21:00:25 UTC
  • Revision ID: package-import@ubuntu.com-20130419210025-tsuvhqufntxj5rsy
Tags: 1.22+dfsg-2ubuntu1
* debian/patches/git_build_with_latest_glib.patch:
  - Backport patch from 1.23 to fix build failure with glib 2.36

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
*
 
3
*   Copyright (c) 2001-2002, Biswapesh Chattopadhyay
 
4
*
 
5
*   This source code is released for free distribution under the terms of the
 
6
*   GNU General Public License.
 
7
*
 
8
*/
 
9
 
 
10
/*!
 
11
 * @file tm_workspace.h
 
12
 The TMWorkspace structure is meant to be used as a singleton to store application
 
13
 wide tag information.
 
14
 
 
15
 The workspace is intended to contain a list of global tags
 
16
 and a set of work objects (projects or individual files). You need not use the
 
17
 workspace, though, to use tag manager, unless you need things like global tags
 
18
 and a place to store all current open projects and individual files. TMWorkspace
 
19
 is derived from TMWorkObject.
 
20
*/
 
21
 
 
22
#include "general.h"
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <unistd.h>
 
27
#include <ctype.h>
 
28
#include <sys/types.h>
 
29
#include <string.h>
 
30
#include <sys/stat.h>
 
31
#ifdef HAVE_GLOB_H
 
32
# include <glob.h>
 
33
#endif
 
34
#include <glib/gstdio.h>
 
35
 
 
36
#include "tm_tag.h"
 
37
#include "tm_workspace.h"
 
38
#include "tm_project.h"
 
39
 
 
40
 
 
41
static TMWorkspace *theWorkspace = NULL;
 
42
guint workspace_class_id = 0;
 
43
 
 
44
static gboolean tm_create_workspace(void)
 
45
{
 
46
        workspace_class_id = tm_work_object_register(tm_workspace_free, tm_workspace_update
 
47
                  , tm_workspace_find_object);
 
48
        theWorkspace = g_new(TMWorkspace, 1);
 
49
        if (FALSE == tm_work_object_init(TM_WORK_OBJECT(theWorkspace),
 
50
                  workspace_class_id, NULL, TRUE))
 
51
        {
 
52
                g_free(theWorkspace);
 
53
                theWorkspace = NULL;
 
54
                g_warning("Failed to initialize workspace");
 
55
                return FALSE;
 
56
        }
 
57
 
 
58
        theWorkspace->global_tags = NULL;
 
59
        theWorkspace->work_objects = NULL;
 
60
        return TRUE;
 
61
}
 
62
 
 
63
void tm_workspace_free(gpointer workspace)
 
64
{
 
65
        guint i;
 
66
 
 
67
        if (workspace != theWorkspace)
 
68
                return;
 
69
 
 
70
#ifdef TM_DEBUG
 
71
        g_message("Workspace destroyed");
 
72
#endif
 
73
 
 
74
        if (theWorkspace)
 
75
        {
 
76
                if (theWorkspace->work_objects)
 
77
                {
 
78
                        for (i=0; i < theWorkspace->work_objects->len; ++i)
 
79
                                tm_work_object_free(theWorkspace->work_objects->pdata[i]);
 
80
                        g_ptr_array_free(theWorkspace->work_objects, TRUE);
 
81
                }
 
82
                if (theWorkspace->global_tags)
 
83
                {
 
84
                        for (i=0; i < theWorkspace->global_tags->len; ++i)
 
85
                                tm_tag_unref(theWorkspace->global_tags->pdata[i]);
 
86
                        g_ptr_array_free(theWorkspace->global_tags, TRUE);
 
87
                }
 
88
                tm_work_object_destroy(TM_WORK_OBJECT(theWorkspace));
 
89
                g_free(theWorkspace);
 
90
                theWorkspace = NULL;
 
91
        }
 
92
}
 
93
 
 
94
const TMWorkspace *tm_get_workspace()
 
95
{
 
96
        if (NULL == theWorkspace)
 
97
                tm_create_workspace();
 
98
        return theWorkspace;
 
99
}
 
100
 
 
101
gboolean tm_workspace_add_object(TMWorkObject *work_object)
 
102
{
 
103
        /* theWorkspace should already have been created otherwise something went wrong */
 
104
        if (NULL == theWorkspace)
 
105
                return FALSE;
 
106
        if (NULL == theWorkspace->work_objects)
 
107
                theWorkspace->work_objects = g_ptr_array_new();
 
108
        g_ptr_array_add(theWorkspace->work_objects, work_object);
 
109
        work_object->parent = TM_WORK_OBJECT(theWorkspace);
 
110
        return TRUE;
 
111
}
 
112
 
 
113
gboolean tm_workspace_remove_object(TMWorkObject *w, gboolean do_free, gboolean update)
 
114
{
 
115
        guint i;
 
116
        if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects)
 
117
                  || (NULL == w))
 
118
                return FALSE;
 
119
 
 
120
 
 
121
        for (i=0; i < theWorkspace->work_objects->len; ++i)
 
122
        {
 
123
                if (theWorkspace->work_objects->pdata[i] == w)
 
124
                {
 
125
                        if (do_free)
 
126
                                tm_work_object_free(w);
 
127
                        g_ptr_array_remove_index_fast(theWorkspace->work_objects, i);
 
128
                        if (update)
 
129
                                tm_workspace_update(TM_WORK_OBJECT(theWorkspace), TRUE, FALSE, FALSE);
 
130
                        return TRUE;
 
131
                }
 
132
        }
 
133
 
 
134
        return FALSE;
 
135
}
 
136
 
 
137
static TMTagAttrType global_tags_sort_attrs[] =
 
138
{
 
139
        tm_tag_attr_name_t, tm_tag_attr_scope_t,
 
140
        tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0
 
141
};
 
142
 
 
143
gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode)
 
144
{
 
145
        gsize orig_len;
 
146
        guchar buf[BUFSIZ];
 
147
        FILE *fp;
 
148
        TMTag *tag;
 
149
        gboolean format_pipe = FALSE;
 
150
 
 
151
        if (NULL == theWorkspace)
 
152
                return FALSE;
 
153
        if (NULL == (fp = g_fopen(tags_file, "r")))
 
154
                return FALSE;
 
155
        if (NULL == theWorkspace->global_tags)
 
156
                theWorkspace->global_tags = g_ptr_array_new();
 
157
        orig_len = theWorkspace->global_tags->len;
 
158
        if ((NULL == fgets((gchar*) buf, BUFSIZ, fp)) || ('\0' == *buf))
 
159
        {
 
160
                fclose(fp);
 
161
                return FALSE; /* early out on error */
 
162
        }
 
163
        else
 
164
        {       /* We read the first line for the format specification. */
 
165
                if (buf[0] == '#' && strstr((gchar*) buf, "format=pipe") != NULL)
 
166
                        format_pipe = TRUE;
 
167
                else if (buf[0] == '#' && strstr((gchar*) buf, "format=tagmanager") != NULL)
 
168
                        format_pipe = FALSE;
 
169
                else
 
170
                {       /* We didn't find a valid format specification, so we try to auto-detect the format
 
171
                         * by counting the pipe characters on the first line and asumme pipe format when
 
172
                         * we find more than one pipe on the line. */
 
173
                        guint i, pipe_cnt = 0;
 
174
                        for (i = 0; i < BUFSIZ && buf[i] != '\0' && pipe_cnt < 2; i++)
 
175
                        {
 
176
                                if (buf[i] == '|')
 
177
                                        pipe_cnt++;
 
178
                        }
 
179
                        format_pipe = (pipe_cnt > 1);
 
180
                }
 
181
                rewind(fp); /* reset the file pointer, to start reading again from the beginning */
 
182
        }
 
183
        while (NULL != (tag = tm_tag_new_from_file(NULL, fp, mode, format_pipe)))
 
184
                g_ptr_array_add(theWorkspace->global_tags, tag);
 
185
        fclose(fp);
 
186
 
 
187
        /* reorder the whole array, because tm_tags_find expects a sorted array */
 
188
        tm_tags_merge(theWorkspace->global_tags, orig_len, global_tags_sort_attrs, TRUE);
 
189
        return TRUE;
 
190
}
 
191
 
 
192
static guint tm_file_inode_hash(gconstpointer key)
 
193
{
 
194
        struct stat file_stat;
 
195
        const char *filename = (const char*)key;
 
196
        if (g_stat(filename, &file_stat) == 0)
 
197
        {
 
198
#ifdef TM_DEBUG
 
199
                g_message ("Hash for '%s' is '%d'\n", filename, file_stat.st_ino);
 
200
#endif
 
201
                return g_direct_hash (GUINT_TO_POINTER (file_stat.st_ino));
 
202
        } else {
 
203
                return 0;
 
204
        }
 
205
}
 
206
 
 
207
static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer user_data)
 
208
{
 
209
        GList **pp_list = (GList**)user_data;
 
210
 
 
211
        if (user_data == NULL)
 
212
                return;
 
213
 
 
214
        *pp_list = g_list_prepend(*pp_list, value);
 
215
}
 
216
 
 
217
static void write_includes_file(FILE *fp, GList *includes_files)
 
218
{
 
219
        GList *node;
 
220
 
 
221
        node = includes_files;
 
222
        while (node)
 
223
        {
 
224
                char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
 
225
                int str_len = strlen(str);
 
226
 
 
227
                fwrite(str, str_len, 1, fp);
 
228
                g_free(str);
 
229
                node = g_list_next(node);
 
230
        }
 
231
}
 
232
 
 
233
 
 
234
static void append_to_temp_file(FILE *fp, GList *file_list)
 
235
{
 
236
        GList *node;
 
237
 
 
238
        node = file_list;
 
239
        while (node)
 
240
        {
 
241
                const char *fname = node->data;
 
242
                char *contents;
 
243
                size_t length;
 
244
                GError *err = NULL;
 
245
 
 
246
                if (! g_file_get_contents(fname, &contents, &length, &err))
 
247
                {
 
248
                        fprintf(stderr, "Unable to read file: %s\n", err->message);
 
249
                        g_error_free(err);
 
250
                }
 
251
                else
 
252
                {
 
253
                        fwrite(contents, length, 1, fp);
 
254
                        fwrite("\n", 1, 1, fp); /* in case file doesn't end in newline (e.g. windows). */
 
255
                        g_free(contents);
 
256
                }
 
257
                node = g_list_next (node);
 
258
        }
 
259
}
 
260
 
 
261
static gchar *create_temp_file(const gchar *tpl)
 
262
{
 
263
        gchar *name;
 
264
        gint fd;
 
265
 
 
266
        fd = g_file_open_tmp(tpl, &name, NULL);
 
267
        if (fd < 0)
 
268
                name = NULL;
 
269
        else
 
270
                close(fd);
 
271
 
 
272
        return name;
 
273
}
 
274
 
 
275
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes,
 
276
        int includes_count, const char *tags_file, int lang)
 
277
{
 
278
#ifdef HAVE_GLOB_H
 
279
        glob_t globbuf;
 
280
        size_t idx_glob;
 
281
#endif
 
282
        int idx_inc;
 
283
        char *command;
 
284
        guint i;
 
285
        FILE *fp;
 
286
        TMWorkObject *source_file;
 
287
        GPtrArray *tags_array;
 
288
        GHashTable *includes_files_hash;
 
289
        GList *includes_files = NULL;
 
290
        gchar *temp_file = create_temp_file("tmp_XXXXXX.cpp");
 
291
        gchar *temp_file2 = create_temp_file("tmp_XXXXXX.cpp");
 
292
 
 
293
        if (NULL == temp_file || NULL == temp_file2 ||
 
294
                NULL == theWorkspace || NULL == (fp = g_fopen(temp_file, "w")))
 
295
        {
 
296
                g_free(temp_file);
 
297
                g_free(temp_file2);
 
298
                return FALSE;
 
299
        }
 
300
 
 
301
        includes_files_hash = g_hash_table_new_full (tm_file_inode_hash,
 
302
                                                                                                 g_direct_equal,
 
303
                                                                                                 NULL, g_free);
 
304
 
 
305
#ifdef HAVE_GLOB_H
 
306
        globbuf.gl_offs = 0;
 
307
 
 
308
        if (includes[0][0] == '"')      /* leading \" char for glob matching */
 
309
        for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
 
310
        {
 
311
                int dirty_len = strlen(includes[idx_inc]);
 
312
                char *clean_path = g_malloc(dirty_len - 1);
 
313
 
 
314
                strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1);
 
315
                clean_path[dirty_len - 2] = 0;
 
316
 
 
317
#ifdef TM_DEBUG
 
318
                g_message ("[o][%s]\n", clean_path);
 
319
#endif
 
320
                glob(clean_path, 0, NULL, &globbuf);
 
321
 
 
322
#ifdef TM_DEBUG
 
323
                g_message ("matches: %d\n", globbuf.gl_pathc);
 
324
#endif
 
325
 
 
326
                for(idx_glob = 0; idx_glob < globbuf.gl_pathc; idx_glob++)
 
327
                {
 
328
#ifdef TM_DEBUG
 
329
                        g_message (">>> %s\n", globbuf.gl_pathv[idx_glob]);
 
330
#endif
 
331
                        if (!g_hash_table_lookup(includes_files_hash,
 
332
                                                                        globbuf.gl_pathv[idx_glob]))
 
333
                        {
 
334
                                char* file_name_copy = strdup(globbuf.gl_pathv[idx_glob]);
 
335
                                g_hash_table_insert(includes_files_hash, file_name_copy,
 
336
                                                                        file_name_copy);
 
337
#ifdef TM_DEBUG
 
338
                                g_message ("Added ...\n");
 
339
#endif
 
340
                        }
 
341
                }
 
342
                globfree(&globbuf);
 
343
                g_free(clean_path);
 
344
        }
 
345
        else
 
346
#endif
 
347
        /* no glob support or globbing not wanted */
 
348
        for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
 
349
        {
 
350
                if (!g_hash_table_lookup(includes_files_hash,
 
351
                                                                        includes[idx_inc]))
 
352
                {
 
353
                        char* file_name_copy = strdup(includes[idx_inc]);
 
354
                        g_hash_table_insert(includes_files_hash, file_name_copy,
 
355
                                                                file_name_copy);
 
356
                }
 
357
        }
 
358
 
 
359
        /* Checks for duplicate file entries which would case trouble */
 
360
        g_hash_table_foreach(includes_files_hash, tm_move_entries_to_g_list,
 
361
                                                 &includes_files);
 
362
 
 
363
        includes_files = g_list_reverse (includes_files);
 
364
 
 
365
#ifdef TM_DEBUG
 
366
        g_message ("writing out files to %s\n", temp_file);
 
367
#endif
 
368
        if (pre_process != NULL)
 
369
                write_includes_file(fp, includes_files);
 
370
        else
 
371
                append_to_temp_file(fp, includes_files);
 
372
 
 
373
        g_list_free (includes_files);
 
374
        g_hash_table_destroy(includes_files_hash);
 
375
        includes_files_hash = NULL;
 
376
        includes_files = NULL;
 
377
        fclose(fp);
 
378
 
 
379
        if (pre_process != NULL)
 
380
        {
 
381
                gint ret;
 
382
                gchar *tmp_errfile = create_temp_file("tmp_XXXXXX");
 
383
                gchar *errors = NULL;
 
384
                command = g_strdup_printf("%s %s >%s 2>%s",
 
385
                                                                pre_process, temp_file, temp_file2, tmp_errfile);
 
386
#ifdef TM_DEBUG
 
387
                g_message("Executing: %s", command);
 
388
#endif
 
389
                ret = system(command);
 
390
                g_free(command);
 
391
                g_unlink(temp_file);
 
392
                g_free(temp_file);
 
393
                g_file_get_contents(tmp_errfile, &errors, NULL, NULL);
 
394
                if (errors && *errors)
 
395
                        g_printerr("%s", errors);
 
396
                g_free(errors);
 
397
                g_unlink(tmp_errfile);
 
398
                g_free(tmp_errfile);
 
399
                if (ret == -1)
 
400
                {
 
401
                        g_unlink(temp_file2);
 
402
                        return FALSE;
 
403
                }
 
404
        }
 
405
        else
 
406
        {
 
407
                /* no pre-processing needed, so temp_file2 = temp_file */
 
408
                g_unlink(temp_file2);
 
409
                g_free(temp_file2);
 
410
                temp_file2 = temp_file;
 
411
                temp_file = NULL;
 
412
        }
 
413
        source_file = tm_source_file_new(temp_file2, TRUE, tm_source_file_get_lang_name(lang));
 
414
        if (NULL == source_file)
 
415
        {
 
416
                g_unlink(temp_file2);
 
417
                return FALSE;
 
418
        }
 
419
        g_unlink(temp_file2);
 
420
        g_free(temp_file2);
 
421
        if ((NULL == source_file->tags_array) || (0 == source_file->tags_array->len))
 
422
        {
 
423
                tm_source_file_free(source_file);
 
424
                return FALSE;
 
425
        }
 
426
        tags_array = tm_tags_extract(source_file->tags_array, tm_tag_max_t);
 
427
        if ((NULL == tags_array) || (0 == tags_array->len))
 
428
        {
 
429
                if (tags_array)
 
430
                        g_ptr_array_free(tags_array, TRUE);
 
431
                tm_source_file_free(source_file);
 
432
                return FALSE;
 
433
        }
 
434
        if (FALSE == tm_tags_sort(tags_array, global_tags_sort_attrs, TRUE))
 
435
        {
 
436
                tm_source_file_free(source_file);
 
437
                return FALSE;
 
438
        }
 
439
        if (NULL == (fp = g_fopen(tags_file, "w")))
 
440
        {
 
441
                tm_source_file_free(source_file);
 
442
                return FALSE;
 
443
        }
 
444
        fprintf(fp, "# format=tagmanager\n");
 
445
        for (i = 0; i < tags_array->len; ++i)
 
446
        {
 
447
                tm_tag_write(TM_TAG(tags_array->pdata[i]), fp, tm_tag_attr_type_t
 
448
                  | tm_tag_attr_scope_t | tm_tag_attr_arglist_t | tm_tag_attr_vartype_t
 
449
                  | tm_tag_attr_pointer_t);
 
450
        }
 
451
        fclose(fp);
 
452
        tm_source_file_free(source_file);
 
453
        g_ptr_array_free(tags_array, TRUE);
 
454
        return TRUE;
 
455
}
 
456
 
 
457
TMWorkObject *tm_workspace_find_object(TMWorkObject *work_object, const char *file_name
 
458
  , gboolean name_only)
 
459
{
 
460
        TMWorkObject *w = NULL;
 
461
        guint i;
 
462
 
 
463
        if (work_object != TM_WORK_OBJECT(theWorkspace))
 
464
                return NULL;
 
465
        if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects)
 
466
                || (0 == theWorkspace->work_objects->len))
 
467
                return NULL;
 
468
        for (i = 0; i < theWorkspace->work_objects->len; ++i)
 
469
        {
 
470
                if (NULL != (w = tm_work_object_find(TM_WORK_OBJECT(theWorkspace->work_objects->pdata[i])
 
471
                          , file_name, name_only)))
 
472
                        return w;
 
473
        }
 
474
        return NULL;
 
475
}
 
476
 
 
477
void tm_workspace_recreate_tags_array(void)
 
478
{
 
479
        guint i, j;
 
480
        TMWorkObject *w;
 
481
        TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t
 
482
                , tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0};
 
483
 
 
484
#ifdef TM_DEBUG
 
485
        g_message("Recreating workspace tags array");
 
486
#endif
 
487
 
 
488
        if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects))
 
489
                return;
 
490
        if (NULL != theWorkspace->work_object.tags_array)
 
491
                g_ptr_array_set_size(theWorkspace->work_object.tags_array, 0);
 
492
        else
 
493
                theWorkspace->work_object.tags_array = g_ptr_array_new();
 
494
 
 
495
#ifdef TM_DEBUG
 
496
        g_message("Total %d objects", theWorkspace->work_objects->len);
 
497
#endif
 
498
        for (i=0; i < theWorkspace->work_objects->len; ++i)
 
499
        {
 
500
                w = TM_WORK_OBJECT(theWorkspace->work_objects->pdata[i]);
 
501
#ifdef TM_DEBUG
 
502
                g_message("Adding tags of %s", w->file_name);
 
503
#endif
 
504
                if ((NULL != w) && (NULL != w->tags_array) && (w->tags_array->len > 0))
 
505
                {
 
506
                        for (j = 0; j < w->tags_array->len; ++j)
 
507
                        {
 
508
                                g_ptr_array_add(theWorkspace->work_object.tags_array,
 
509
                                          w->tags_array->pdata[j]);
 
510
                        }
 
511
                }
 
512
        }
 
513
#ifdef TM_DEBUG
 
514
        g_message("Total: %d tags", theWorkspace->work_object.tags_array->len);
 
515
#endif
 
516
        tm_tags_sort(theWorkspace->work_object.tags_array, sort_attrs, TRUE);
 
517
}
 
518
 
 
519
gboolean tm_workspace_update(TMWorkObject *workspace, gboolean force
 
520
  , gboolean recurse, gboolean __unused__ update_parent)
 
521
{
 
522
        guint i;
 
523
        gboolean update_tags = force;
 
524
 
 
525
#ifdef TM_DEBUG
 
526
        g_message("Updating workspace");
 
527
#endif
 
528
 
 
529
        if (workspace != TM_WORK_OBJECT(theWorkspace))
 
530
                return FALSE;
 
531
        if (NULL == theWorkspace)
 
532
                return TRUE;
 
533
        if ((recurse) && (theWorkspace->work_objects))
 
534
        {
 
535
                for (i=0; i < theWorkspace->work_objects->len; ++i)
 
536
                {
 
537
                        if (TRUE == tm_work_object_update(TM_WORK_OBJECT(
 
538
                                  theWorkspace->work_objects->pdata[i]), FALSE, TRUE, FALSE))
 
539
                                update_tags = TRUE;
 
540
                }
 
541
        }
 
542
        if (update_tags)
 
543
                tm_workspace_recreate_tags_array();
 
544
        /* workspace->analyze_time = time(NULL); */
 
545
        return update_tags;
 
546
}
 
547
 
 
548
void tm_workspace_dump(void)
 
549
{
 
550
        if (theWorkspace)
 
551
        {
 
552
#ifdef TM_DEBUG
 
553
                g_message("Dumping TagManager workspace tree..");
 
554
#endif
 
555
                tm_work_object_dump(TM_WORK_OBJECT(theWorkspace));
 
556
                if (theWorkspace->work_objects)
 
557
                {
 
558
                        guint i;
 
559
                        for (i=0; i < theWorkspace->work_objects->len; ++i)
 
560
                        {
 
561
                                if (IS_TM_PROJECT(TM_WORK_OBJECT(theWorkspace->work_objects->pdata[i])))
 
562
                                        tm_project_dump(TM_PROJECT(theWorkspace->work_objects->pdata[i]));
 
563
                                else
 
564
                                        tm_work_object_dump(TM_WORK_OBJECT(theWorkspace->work_objects->pdata[i]));
 
565
                        }
 
566
                }
 
567
        }
 
568
}
 
569
 
 
570
const GPtrArray *tm_workspace_find(const char *name, int type, TMTagAttrType *attrs
 
571
 , gboolean partial, langType lang)
 
572
{
 
573
        static GPtrArray *tags = NULL;
 
574
        TMTag **matches[2];
 
575
        int len, tagCount[2]={0,0}, tagIter;
 
576
        gint tags_lang;
 
577
 
 
578
        if ((!theWorkspace) || (!name))
 
579
                return NULL;
 
580
        len = strlen(name);
 
581
        if (!len)
 
582
                return NULL;
 
583
        if (tags)
 
584
                g_ptr_array_set_size(tags, 0);
 
585
        else
 
586
                tags = g_ptr_array_new();
 
587
 
 
588
        matches[0] = tm_tags_find(theWorkspace->work_object.tags_array, name, partial, &tagCount[0]);
 
589
        matches[1] = tm_tags_find(theWorkspace->global_tags, name, partial, &tagCount[1]);
 
590
 
 
591
        /* file tags */
 
592
        if (matches[0] && *matches[0])
 
593
        {
 
594
                /* tag->atts.file.lang contains the line of the tag and
 
595
                 * tags->atts.entry.file->lang contains the language */
 
596
                tags_lang = (*matches[0])->atts.entry.file->lang;
 
597
 
 
598
                for (tagIter=0;tagIter<tagCount[0];++tagIter)
 
599
                {
 
600
                        if ((type & (*matches[0])->type) && (lang == -1 || tags_lang == lang))
 
601
                                g_ptr_array_add(tags, *matches[0]);
 
602
                        if (partial)
 
603
                        {
 
604
                                if (0 != strncmp((*matches[0])->name, name, len))
 
605
                                        break;
 
606
                        }
 
607
                        else
 
608
                        {
 
609
                                if (0 != strcmp((*matches[0])->name, name))
 
610
                                        break;
 
611
                        }
 
612
                        ++ matches[0];
 
613
                }
 
614
        }
 
615
 
 
616
        /* global tags */
 
617
        if (matches[1] && *matches[1])
 
618
        {
 
619
                int tags_lang_alt = 0;
 
620
                /* tag->atts.file.lang contains the language and
 
621
                 * tags->atts.entry.file is NULL */
 
622
                tags_lang = (*matches[1])->atts.file.lang;
 
623
                /* tags_lang_alt is used to load C global tags only once for C and C++
 
624
                 * lang = 1 is C++, lang = 0 is C
 
625
                 * if we have lang 0, than accept also lang 1 for C++ */
 
626
                if (tags_lang == 0)     /* C or C++ */
 
627
                        tags_lang_alt = 1;
 
628
                else
 
629
                        tags_lang_alt = tags_lang; /* otherwise just ignore it */
 
630
 
 
631
                for (tagIter=0;tagIter<tagCount[1];++tagIter)
 
632
                {
 
633
                        if ((type & (*matches[1])->type) && (lang == -1 ||
 
634
                                tags_lang == lang || tags_lang_alt == lang))
 
635
                                g_ptr_array_add(tags, *matches[1]);
 
636
 
 
637
                        if (partial)
 
638
                        {
 
639
                                if (0 != strncmp((*matches[1])->name, name, len))
 
640
                                        break;
 
641
                        }
 
642
                        else
 
643
                        {
 
644
                                if (0 != strcmp((*matches[1])->name, name))
 
645
                                        break;
 
646
                        }
 
647
                        ++ matches[1];
 
648
                }
 
649
        }
 
650
 
 
651
        if (attrs)
 
652
                tm_tags_sort(tags, attrs, TRUE);
 
653
        return tags;
 
654
}
 
655
 
 
656
static gboolean match_langs(gint lang, const TMTag *tag)
 
657
{
 
658
        if (tag->atts.entry.file)
 
659
        {       /* workspace tag */
 
660
                if (lang == tag->atts.entry.file->lang)
 
661
                        return TRUE;
 
662
        }
 
663
        else
 
664
        {       /* global tag */
 
665
                if (lang == tag->atts.file.lang)
 
666
                        return TRUE;
 
667
        }
 
668
        return FALSE;
 
669
}
 
670
 
 
671
/* scope can be NULL.
 
672
 * lang can be -1 */
 
673
static int
 
674
fill_find_tags_array (GPtrArray *dst, const GPtrArray *src,
 
675
                                          const char *name, const char *scope, int type, gboolean partial,
 
676
                                          gint lang, gboolean first)
 
677
{
 
678
        TMTag **match;
 
679
        int tagIter, count;
 
680
 
 
681
        if ((!src) || (!dst) || (!name) || (!*name))
 
682
                return 0;
 
683
 
 
684
        match = tm_tags_find (src, name, partial, &count);
 
685
        if (count && match && *match)
 
686
        {
 
687
                for (tagIter = 0; tagIter < count; ++tagIter)
 
688
                {
 
689
                        if (! scope || (match[tagIter]->atts.entry.scope &&
 
690
                                0 == strcmp(match[tagIter]->atts.entry.scope, scope)))
 
691
                        {
 
692
                                if (type & match[tagIter]->type)
 
693
                                if (lang == -1 || match_langs(lang, match[tagIter]))
 
694
                                {
 
695
                                        g_ptr_array_add (dst, match[tagIter]);
 
696
                                        if (first)
 
697
                                                break;
 
698
                                }
 
699
                        }
 
700
                }
 
701
        }
 
702
        return dst->len;
 
703
}
 
704
 
 
705
 
 
706
/* adapted from tm_workspace_find, Anjuta 2.02 */
 
707
const GPtrArray *
 
708
tm_workspace_find_scoped (const char *name, const char *scope, gint type,
 
709
                TMTagAttrType *attrs, gboolean partial, langType lang, gboolean global_search)
 
710
{
 
711
        static GPtrArray *tags = NULL;
 
712
 
 
713
        if ((!theWorkspace))
 
714
                return NULL;
 
715
 
 
716
        if (tags)
 
717
                g_ptr_array_set_size (tags, 0);
 
718
        else
 
719
                tags = g_ptr_array_new ();
 
720
 
 
721
        fill_find_tags_array (tags, theWorkspace->work_object.tags_array,
 
722
                                                  name, scope, type, partial, lang, FALSE);
 
723
        if (global_search)
 
724
        {
 
725
                /* for a scoped tag, I think we always want the same language */
 
726
                fill_find_tags_array (tags, theWorkspace->global_tags,
 
727
                                                          name, scope, type, partial, lang, FALSE);
 
728
        }
 
729
        if (attrs)
 
730
                tm_tags_sort (tags, attrs, TRUE);
 
731
        return tags;
 
732
}
 
733
 
 
734
 
 
735
const TMTag *
 
736
tm_get_current_function (GPtrArray * file_tags, const gulong line)
 
737
{
 
738
        GPtrArray *const local = tm_tags_extract (file_tags, tm_tag_function_t);
 
739
        if (local && local->len)
 
740
        {
 
741
                guint i;
 
742
                TMTag *tag, *function_tag = NULL;
 
743
                gulong function_line = 0;
 
744
                glong delta;
 
745
 
 
746
                for (i = 0; (i < local->len); ++i)
 
747
                {
 
748
                        tag = TM_TAG (local->pdata[i]);
 
749
                        delta = line - tag->atts.entry.line;
 
750
                        if (delta >= 0 && (gulong)delta < line - function_line)
 
751
                        {
 
752
                                function_tag = tag;
 
753
                                function_line = tag->atts.entry.line;
 
754
                        }
 
755
                }
 
756
                g_ptr_array_free (local, TRUE);
 
757
                return function_tag;
 
758
        }
 
759
        return NULL;
 
760
}
 
761
 
 
762
 
 
763
static int
 
764
find_scope_members_tags (const GPtrArray * all, GPtrArray * tags,
 
765
                                                 const langType langJava, const char *name,
 
766
                                                 const char *filename, gboolean no_definitions)
 
767
{
 
768
        GPtrArray *local = g_ptr_array_new ();
 
769
        unsigned int i;
 
770
        TMTag *tag;
 
771
        size_t len = strlen (name);
 
772
        for (i = 0; (i < all->len); ++i)
 
773
        {
 
774
                tag = TM_TAG (all->pdata[i]);
 
775
                if (no_definitions && filename && tag->atts.entry.file &&
 
776
                        0 != strcmp (filename,
 
777
                                                 tag->atts.entry.file->work_object.short_name))
 
778
                {
 
779
                        continue;
 
780
                }
 
781
                if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
 
782
                {
 
783
                        if (0 == strncmp (name, tag->atts.entry.scope, len))
 
784
                        {
 
785
                                g_ptr_array_add (local, tag);
 
786
                        }
 
787
                }
 
788
        }
 
789
        if (local->len > 0)
 
790
        {
 
791
                unsigned int j;
 
792
                TMTag *tag2;
 
793
                char backup = 0;
 
794
                char *s_backup = NULL;
 
795
                char *var_type = NULL;
 
796
                char *scope;
 
797
                for (i = 0; (i < local->len); ++i)
 
798
                {
 
799
                        tag = TM_TAG (local->pdata[i]);
 
800
                        scope = tag->atts.entry.scope;
 
801
                        if (scope && 0 == strcmp (name, scope))
 
802
                        {
 
803
                                g_ptr_array_add (tags, tag);
 
804
                                continue;
 
805
                        }
 
806
                        s_backup = NULL;
 
807
                        j = 0;                          /* someone could write better code :P */
 
808
                        while (scope)
 
809
                        {
 
810
                                if (s_backup)
 
811
                                {
 
812
                                        backup = s_backup[0];
 
813
                                        s_backup[0] = '\0';
 
814
                                        if (0 == strcmp (name, tag->atts.entry.scope))
 
815
                                        {
 
816
                                                j = local->len;
 
817
                                                s_backup[0] = backup;
 
818
                                                break;
 
819
                                        }
 
820
                                }
 
821
                                if (tag->atts.entry.file
 
822
                                        && tag->atts.entry.file->lang == langJava)
 
823
                                {
 
824
                                        scope = strrchr (tag->atts.entry.scope, '.');
 
825
                                        if (scope)
 
826
                                                var_type = scope + 1;
 
827
                                }
 
828
                                else
 
829
                                {
 
830
                                        scope = strrchr (tag->atts.entry.scope, ':');
 
831
                                        if (scope)
 
832
                                        {
 
833
                                                var_type = scope + 1;
 
834
                                                scope--;
 
835
                                        }
 
836
                                }
 
837
                                if (s_backup)
 
838
                                {
 
839
                                        s_backup[0] = backup;
 
840
                                }
 
841
                                if (scope)
 
842
                                {
 
843
                                        if (s_backup)
 
844
                                        {
 
845
                                                backup = s_backup[0];
 
846
                                                s_backup[0] = '\0';
 
847
                                        }
 
848
                                        for (j = 0; (j < local->len); ++j)
 
849
                                        {
 
850
                                                if (i == j)
 
851
                                                        continue;
 
852
                                                tag2 = TM_TAG (local->pdata[j]);
 
853
                                                if (tag2->atts.entry.var_type &&
 
854
                                                        0 == strcmp (var_type, tag2->atts.entry.var_type))
 
855
                                                {
 
856
                                                        break;
 
857
                                                }
 
858
                                        }
 
859
                                        if (s_backup)
 
860
                                                s_backup[0] = backup;
 
861
                                }
 
862
                                if (j < local->len)
 
863
                                {
 
864
                                        break;
 
865
                                }
 
866
                                s_backup = scope;
 
867
                        }
 
868
                        if (j == local->len)
 
869
                        {
 
870
                                g_ptr_array_add (tags, tag);
 
871
                        }
 
872
                }
 
873
        }
 
874
        g_ptr_array_free (local, TRUE);
 
875
        return (int) tags->len;
 
876
}
 
877
 
 
878
 
 
879
#if 0
 
880
static int
 
881
find_namespace_members_tags (const GPtrArray * all, GPtrArray * tags,
 
882
                                                        const langType langJava, const char *name,
 
883
                                                        const char *filename)
 
884
{
 
885
        GPtrArray *local = g_ptr_array_new ();
 
886
        unsigned int i;
 
887
        TMTag *tag;
 
888
        size_t len = strlen (name);
 
889
 
 
890
        g_return_val_if_fail (all != NULL, 0);
 
891
 
 
892
        for (i = 0; (i < all->len); ++i)
 
893
        {
 
894
                tag = TM_TAG (all->pdata[i]);
 
895
                if (filename && tag->atts.entry.file &&
 
896
                        0 != strcmp (filename,
 
897
                                                 tag->atts.entry.file->work_object.short_name))
 
898
                {
 
899
                        continue;
 
900
                }
 
901
 
 
902
                if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
 
903
                {
 
904
                        if (0 == strncmp (name, tag->atts.entry.scope, len))
 
905
                        {
 
906
                                g_ptr_array_add (local, tag);
 
907
                        }
 
908
                }
 
909
        }
 
910
 
 
911
        if (local->len > 0)
 
912
        {
 
913
                char *scope;
 
914
                for (i = 0; (i < local->len); ++i)
 
915
                {
 
916
                        tag = TM_TAG (local->pdata[i]);
 
917
                        scope = tag->atts.entry.scope;
 
918
 
 
919
                        /* if we wanna complete something like
 
920
                         * namespace1::
 
921
                         * we'll just return the tags that have "namespace1"
 
922
                         * as their scope. So we won't return classes/members/namespaces
 
923
                         * under, for example, namespace2, where namespace1::namespace2
 
924
                         */
 
925
                        if (scope && 0 == strcmp (name, scope))
 
926
                        {
 
927
                                g_ptr_array_add (tags, tag);
 
928
                        }
 
929
                }
 
930
        }
 
931
 
 
932
        g_ptr_array_free (local, TRUE);
 
933
        return (int) tags->len;
 
934
}
 
935
 
 
936
const GPtrArray *
 
937
tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *name,
 
938
                                                                 gboolean search_global)
 
939
{
 
940
        static GPtrArray *tags = NULL;
 
941
        GPtrArray *local = NULL;
 
942
        char *new_name = (char *) name;
 
943
        char *filename = NULL;
 
944
        int found = 0, del = 0;
 
945
        static langType langJava = -1;
 
946
        TMTag *tag = NULL;
 
947
 
 
948
        g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL);
 
949
 
 
950
        if (!tags)
 
951
                tags = g_ptr_array_new ();
 
952
 
 
953
        while (1)
 
954
        {
 
955
                const GPtrArray *tags2;
 
956
                int got = 0, types = (tm_tag_class_t | tm_tag_namespace_t |
 
957
                                                                tm_tag_struct_t | tm_tag_typedef_t |
 
958
                                                                tm_tag_union_t | tm_tag_enum_t);
 
959
 
 
960
                if (file_tags)
 
961
                {
 
962
                        g_ptr_array_set_size (tags, 0);
 
963
                        got = fill_find_tags_array (tags, file_tags,
 
964
                                                                                  new_name, NULL, types, FALSE, -1, FALSE);
 
965
                }
 
966
 
 
967
 
 
968
                if (got)
 
969
                {
 
970
                        tags2 = tags;
 
971
                }
 
972
                else
 
973
                {
 
974
                        TMTagAttrType attrs[] = {
 
975
                                tm_tag_attr_name_t, tm_tag_attr_type_t,
 
976
                                tm_tag_attr_none_t
 
977
                        };
 
978
                        tags2 = tm_workspace_find (new_name, types, attrs, FALSE, -1);
 
979
                }
 
980
 
 
981
                if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0])))
 
982
                {
 
983
                        if (tag->type == tm_tag_typedef_t && tag->atts.entry.var_type
 
984
                                && tag->atts.entry.var_type[0] != '\0')
 
985
                        {
 
986
                                new_name = tag->atts.entry.var_type;
 
987
                                continue;
 
988
                        }
 
989
                        filename = (tag->atts.entry.file ?
 
990
                                                tag->atts.entry.file->work_object.short_name : NULL);
 
991
                        if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
 
992
                        {
 
993
                                del = 1;
 
994
                                if (tag->atts.entry.file &&
 
995
                                        tag->atts.entry.file->lang == langJava)
 
996
                                {
 
997
                                        new_name = g_strdup_printf ("%s.%s",
 
998
                                                                                                tag->atts.entry.scope,
 
999
                                                                                                new_name);
 
1000
                                }
 
1001
                                else
 
1002
                                {
 
1003
                                        new_name = g_strdup_printf ("%s::%s",
 
1004
                                                                                                tag->atts.entry.scope,
 
1005
                                                                                                new_name);
 
1006
                                }
 
1007
                        }
 
1008
                        break;
 
1009
                }
 
1010
                else
 
1011
                {
 
1012
                        return NULL;
 
1013
                }
 
1014
        }
 
1015
 
 
1016
        g_ptr_array_set_size (tags, 0);
 
1017
 
 
1018
        if (tag && tag->atts.entry.file)
 
1019
        {
 
1020
                local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array,
 
1021
                                                                 (tm_tag_function_t |
 
1022
                                                                  tm_tag_field_t | tm_tag_enumerator_t |
 
1023
                                                                  tm_tag_namespace_t | tm_tag_class_t ));
 
1024
        }
 
1025
        else
 
1026
        {
 
1027
                local = tm_tags_extract (theWorkspace->work_object.tags_array,
 
1028
                                                                 (tm_tag_function_t | tm_tag_prototype_t |
 
1029
                                                                  tm_tag_member_t |
 
1030
                                                                  tm_tag_field_t | tm_tag_enumerator_t |
 
1031
                                                                  tm_tag_namespace_t | tm_tag_class_t ));
 
1032
        }
 
1033
 
 
1034
        if (local)
 
1035
        {
 
1036
                found = find_namespace_members_tags (local, tags,
 
1037
                                                                                 langJava, new_name, filename);
 
1038
                g_ptr_array_free (local, TRUE);
 
1039
        }
 
1040
 
 
1041
 
 
1042
        if (!found && search_global)
 
1043
        {
 
1044
                GPtrArray *global = tm_tags_extract (theWorkspace->global_tags,
 
1045
                                                                                         (tm_tag_member_t |
 
1046
                                                                                          tm_tag_prototype_t |
 
1047
                                                                                          tm_tag_field_t |
 
1048
                                                                                          tm_tag_method_t |
 
1049
                                                                                          tm_tag_function_t |
 
1050
                                                                                          tm_tag_enumerator_t |
 
1051
                                                                                          tm_tag_namespace_t |
 
1052
                                                                                          tm_tag_class_t ));
 
1053
 
 
1054
                if (global)
 
1055
                {
 
1056
                        find_namespace_members_tags (global, tags, langJava,
 
1057
                                                                         new_name, filename);
 
1058
/*/
 
1059
                        DEBUG_PRINT ("returning these");
 
1060
                    gint i;
 
1061
                        for (i=0; i < tags->len; i++) {
 
1062
                                TMTag *cur_tag;
 
1063
 
 
1064
                                cur_tag = (TMTag*)g_ptr_array_index (tags, i);
 
1065
                                tm_tag_print (cur_tag, stdout );
 
1066
                        }
 
1067
/*/
 
1068
                        g_ptr_array_free (global, TRUE);
 
1069
                }
 
1070
        }
 
1071
 
 
1072
 
 
1073
        if (del)
 
1074
        {
 
1075
                g_free (new_name);
 
1076
        }
 
1077
 
 
1078
        return tags;
 
1079
}
 
1080
#endif
 
1081
 
 
1082
const GPtrArray *
 
1083
tm_workspace_find_scope_members (const GPtrArray * file_tags, const char *name,
 
1084
                                                                 gboolean search_global, gboolean no_definitions)
 
1085
{
 
1086
        static GPtrArray *tags = NULL;
 
1087
        GPtrArray *local = NULL;
 
1088
        char *new_name = (char *) name;
 
1089
        char *filename = NULL;
 
1090
        int found = 0, del = 0;
 
1091
        static langType langJava = -1;
 
1092
        TMTag *tag = NULL;
 
1093
 
 
1094
        /* FIXME */
 
1095
        /* langJava = getNamedLanguage ("Java"); */
 
1096
 
 
1097
        g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL);
 
1098
 
 
1099
        if (!tags)
 
1100
                tags = g_ptr_array_new ();
 
1101
 
 
1102
        while (1)
 
1103
        {
 
1104
                const GPtrArray *tags2;
 
1105
                int got = 0, types = (tm_tag_class_t | tm_tag_namespace_t |
 
1106
                                                                tm_tag_struct_t | tm_tag_typedef_t |
 
1107
                                                                tm_tag_union_t | tm_tag_enum_t);
 
1108
 
 
1109
                if (file_tags)
 
1110
                {
 
1111
                        g_ptr_array_set_size (tags, 0);
 
1112
                        got = fill_find_tags_array (tags, file_tags,
 
1113
                                                                                  new_name, NULL, types, FALSE, -1, FALSE);
 
1114
                }
 
1115
                if (got)
 
1116
                {
 
1117
                        tags2 = tags;
 
1118
                }
 
1119
                else
 
1120
                {
 
1121
                        TMTagAttrType attrs[] = {
 
1122
                                tm_tag_attr_name_t, tm_tag_attr_type_t,
 
1123
                                tm_tag_attr_none_t
 
1124
                        };
 
1125
                        tags2 = tm_workspace_find (new_name, types, attrs, FALSE, -1);
 
1126
                }
 
1127
 
 
1128
                if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0])))
 
1129
                {
 
1130
                        if (tag->type == tm_tag_typedef_t && tag->atts.entry.var_type
 
1131
                                && tag->atts.entry.var_type[0] != '\0')
 
1132
                        {
 
1133
                                char *tmp_name;
 
1134
                                tmp_name = tag->atts.entry.var_type;
 
1135
                                if (strcmp(tmp_name, new_name) == 0) {
 
1136
                                        new_name = NULL;
 
1137
                                }
 
1138
                                else {
 
1139
                                        new_name = tmp_name;
 
1140
                                }
 
1141
                                continue;
 
1142
                        }
 
1143
                        filename = (tag->atts.entry.file ?
 
1144
                                                tag->atts.entry.file->work_object.short_name : NULL);
 
1145
                        if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
 
1146
                        {
 
1147
                                del = 1;
 
1148
                                if (tag->atts.entry.file &&
 
1149
                                        tag->atts.entry.file->lang == langJava)
 
1150
                                {
 
1151
                                        new_name = g_strdup_printf ("%s.%s",
 
1152
                                                                                                tag->atts.entry.scope,
 
1153
                                                                                                new_name);
 
1154
                                }
 
1155
                                else
 
1156
                                {
 
1157
                                        new_name = g_strdup_printf ("%s::%s",
 
1158
                                                                                                tag->atts.entry.scope,
 
1159
                                                                                                new_name);
 
1160
                                }
 
1161
                        }
 
1162
                        break;
 
1163
                }
 
1164
                else
 
1165
                {
 
1166
                        return NULL;
 
1167
                }
 
1168
        }
 
1169
 
 
1170
        g_ptr_array_set_size (tags, 0);
 
1171
 
 
1172
        if (no_definitions && tag && tag->atts.entry.file)
 
1173
        {
 
1174
                local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array,
 
1175
                                                                 (tm_tag_function_t | tm_tag_prototype_t |
 
1176
                                                                  tm_tag_member_t | tm_tag_field_t |
 
1177
                                                                  tm_tag_method_t | tm_tag_enumerator_t));
 
1178
        }
 
1179
        else
 
1180
        {
 
1181
                local = tm_tags_extract (theWorkspace->work_object.tags_array,
 
1182
                                                                 (tm_tag_function_t | tm_tag_prototype_t |
 
1183
                                                                  tm_tag_member_t | tm_tag_field_t |
 
1184
                                                                  tm_tag_method_t | tm_tag_enumerator_t));
 
1185
        }
 
1186
        if (local)
 
1187
        {
 
1188
                found = find_scope_members_tags (local, tags, langJava, new_name,
 
1189
                                                                                 filename, no_definitions);
 
1190
                g_ptr_array_free (local, TRUE);
 
1191
        }
 
1192
        if (!found && search_global)
 
1193
        {
 
1194
                GPtrArray *global = tm_tags_extract (theWorkspace->global_tags,
 
1195
                                                                                         (tm_tag_member_t |
 
1196
                                                                                          tm_tag_prototype_t |
 
1197
                                                                                          tm_tag_field_t |
 
1198
                                                                                          tm_tag_method_t |
 
1199
                                                                                          tm_tag_function_t |
 
1200
                                                                                          tm_tag_enumerator_t
 
1201
                                                                                          |tm_tag_struct_t | tm_tag_typedef_t |
 
1202
                                                                                          tm_tag_union_t | tm_tag_enum_t));
 
1203
                if (global)
 
1204
                {
 
1205
                        find_scope_members_tags (global, tags, langJava, new_name,
 
1206
                                                                         filename, no_definitions);
 
1207
                        g_ptr_array_free (global, TRUE);
 
1208
                }
 
1209
        }
 
1210
        if (del)
 
1211
        {
 
1212
                g_free (new_name);
 
1213
        }
 
1214
 
 
1215
        return tags;
 
1216
}
 
1217
 
 
1218
const GPtrArray *tm_workspace_get_parents(const gchar *name)
 
1219
{
 
1220
        static TMTagAttrType type[] = { tm_tag_attr_name_t, tm_tag_attr_none_t };
 
1221
        static GPtrArray *parents = NULL;
 
1222
        const GPtrArray *matches;
 
1223
        guint i = 0;
 
1224
        guint j;
 
1225
        gchar **klasses;
 
1226
        gchar **klass;
 
1227
        TMTag *tag;
 
1228
 
 
1229
        g_return_val_if_fail(name && isalpha(*name),NULL);
 
1230
 
 
1231
        if (NULL == parents)
 
1232
                parents = g_ptr_array_new();
 
1233
        else
 
1234
                g_ptr_array_set_size(parents, 0);
 
1235
        matches = tm_workspace_find(name, tm_tag_class_t, type, FALSE, -1);
 
1236
        if ((NULL == matches) || (0 == matches->len))
 
1237
                return NULL;
 
1238
        g_ptr_array_add(parents, matches->pdata[0]);
 
1239
        while (i < parents->len)
 
1240
        {
 
1241
                tag = TM_TAG(parents->pdata[i]);
 
1242
                if ((NULL != tag->atts.entry.inheritance) && (isalpha(tag->atts.entry.inheritance[0])))
 
1243
                {
 
1244
                        klasses = g_strsplit(tag->atts.entry.inheritance, ",", 10);
 
1245
                        for (klass = klasses; (NULL != *klass); ++ klass)
 
1246
                        {
 
1247
                                for (j=0; j < parents->len; ++j)
 
1248
                                {
 
1249
                                        if (0 == strcmp(*klass, TM_TAG(parents->pdata[j])->name))
 
1250
                                                break;
 
1251
                                }
 
1252
                                if (parents->len == j)
 
1253
                                {
 
1254
                                        matches = tm_workspace_find(*klass, tm_tag_class_t, type, FALSE, -1);
 
1255
                                        if ((NULL != matches) && (0 < matches->len))
 
1256
                                                g_ptr_array_add(parents, matches->pdata[0]);
 
1257
                                }
 
1258
                        }
 
1259
                        g_strfreev(klasses);
 
1260
                }
 
1261
                ++ i;
 
1262
        }
 
1263
        return parents;
 
1264
}