Version bump.
[geany-mirror.git] / tagmanager / tm_work_object.c
blob2f7fe894bb83b2e73b5c65a225f97e30d0f96ec7
1 /*
3 * Copyright (c) 2001-2002, Biswapesh Chattopadhyay
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
8 */
10 /**
11 * @file tm_work_object.h
12 * A TMWorkObject structure is the base class for TMSourceFile and TMProject.
15 #include "general.h" /* must always come first */
17 #include <stdio.h>
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <glib/gstdio.h>
23 #ifdef G_OS_WIN32
24 # define VC_EXTRALEAN
25 # define WIN32_LEAN_AND_MEAN
26 # include <windows.h> /* for GetFullPathName */
27 #endif
29 #include "tm_tag.h"
30 #include "tm_work_object.h"
32 static GPtrArray *s_work_object_subclasses = NULL;
35 static int get_path_max(const char *path)
37 #ifdef PATH_MAX
38 return PATH_MAX;
39 #else
40 int path_max = pathconf(path, _PC_PATH_MAX);
41 if (path_max <= 0)
42 path_max = 4096;
43 return path_max;
44 #endif
48 #ifdef G_OS_WIN32
49 /* realpath implementation for Windows found at http://bugzilla.gnome.org/show_bug.cgi?id=342926
50 * this one is better than e.g. liberty's lrealpath because this one uses Win32 API and works
51 * with special chars within the filename */
52 static char *realpath (const char *pathname, char *resolved_path)
54 int size;
56 if (resolved_path != NULL)
58 int path_max = get_path_max(pathname);
59 size = GetFullPathNameA (pathname, path_max, resolved_path, NULL);
60 if (size > path_max)
61 return NULL;
62 else
63 return resolved_path;
65 else
67 size = GetFullPathNameA (pathname, 0, NULL, NULL);
68 resolved_path = g_new0 (char, size);
69 GetFullPathNameA (pathname, size, resolved_path, NULL);
70 return resolved_path;
73 #endif
75 gchar *tm_get_real_path(const gchar *file_name)
77 if (file_name)
79 gsize len = get_path_max(file_name) + 1;
80 gchar *path = g_malloc0(len);
82 if (realpath(file_name, path))
83 return path;
84 else
85 g_free(path);
87 return NULL;
90 guint tm_work_object_register(GFreeFunc free_func, TMUpdateFunc update_func, TMFindFunc find_func)
92 TMWorkObjectClass *object_class;
93 if (NULL == s_work_object_subclasses)
95 s_work_object_subclasses = g_ptr_array_new();
96 object_class = g_new(TMWorkObjectClass, 1);
97 object_class->free_func = tm_work_object_free;
98 object_class->update_func = NULL;
99 object_class->find_func = NULL;
100 g_ptr_array_add(s_work_object_subclasses, object_class);
102 object_class = g_new(TMWorkObjectClass, 1);
103 object_class->free_func = free_func;
104 object_class->update_func = update_func;
105 object_class->find_func = find_func;
106 g_ptr_array_add(s_work_object_subclasses, object_class);
107 return (s_work_object_subclasses->len - 1);
110 gboolean tm_work_object_init(TMWorkObject *work_object, guint type, const char *file_name
111 , gboolean create)
113 struct stat s;
114 int status;
116 if (file_name != NULL)
118 if (0 != (status = g_stat(file_name, &s)))
120 if (create)
122 FILE *f;
123 if (NULL == (f = g_fopen(file_name, "a+")))
125 g_warning("Unable to create file %s", file_name);
126 return FALSE;
128 fclose(f);
129 status = g_stat(file_name, &s);
132 if (0 != status)
134 /* g_warning("Unable to stat %s", file_name);*/
135 return FALSE;
137 if (!S_ISREG(s.st_mode))
139 g_warning("%s: Not a regular file", file_name);
140 return FALSE;
142 work_object->file_name = tm_get_real_path(file_name);
143 work_object->short_name = strrchr(work_object->file_name, '/');
144 if (work_object->short_name)
145 ++ work_object->short_name;
146 else
147 work_object->short_name = work_object->file_name;
149 else
151 work_object->file_name = NULL;
152 work_object->short_name = NULL;
154 work_object->type = type;
155 work_object->parent = NULL;
156 work_object->analyze_time = 0;
157 work_object->tags_array = NULL;
158 return TRUE;
162 time_t tm_get_file_timestamp(const char *file_name)
164 struct stat s;
166 g_return_val_if_fail(file_name, 0);
168 if (0 != g_stat(file_name, &s))
170 return (time_t) 0;
172 else
173 return s.st_mtime;
176 gboolean tm_work_object_is_changed(TMWorkObject *work_object)
178 return (gboolean) (work_object->analyze_time < tm_get_file_timestamp(work_object->file_name));
182 TMWorkObject *tm_work_object_new(guint type, const char *file_name, gboolean create)
184 TMWorkObject *work_object = g_new(TMWorkObject, 1);
185 if (!tm_work_object_init(work_object, type, file_name, create))
187 g_free(work_object);
188 return NULL;
190 return work_object;
193 void tm_work_object_destroy(TMWorkObject *work_object)
195 if (work_object)
197 g_free(work_object->file_name);
198 if (work_object->tags_array)
199 g_ptr_array_free(work_object->tags_array, TRUE);
203 void tm_work_object_free(gpointer work_object)
205 if (NULL != work_object)
207 TMWorkObject *w = (TMWorkObject *) work_object;
208 if ((w->type > 0) && (w->type < s_work_object_subclasses->len) &&
209 (s_work_object_subclasses->pdata[w->type] != NULL))
211 GFreeFunc free_func =
212 ((TMWorkObjectClass *)s_work_object_subclasses->pdata[w->type])->free_func;
213 if (NULL != free_func)
214 free_func(work_object);
215 return;
217 tm_work_object_destroy(w);
218 g_free(work_object);
222 void tm_work_object_write_tags(TMWorkObject *work_object, FILE *file, guint attrs)
224 if (NULL != work_object->tags_array)
226 guint i;
227 for (i=0; i < work_object->tags_array->len; ++i)
228 tm_tag_write((TMTag *) g_ptr_array_index(work_object->tags_array, i)
229 , file, (TMTagAttrType) attrs);
233 gboolean tm_work_object_update(TMWorkObject *work_object, gboolean force
234 , gboolean recurse, gboolean update_parent)
236 if ((NULL != work_object) && (work_object->type > 0) &&
237 (work_object->type < s_work_object_subclasses->len) &&
238 (s_work_object_subclasses->pdata[work_object->type] != NULL))
240 TMUpdateFunc update_func =
241 ((TMWorkObjectClass *)s_work_object_subclasses->pdata[work_object->type])->update_func;
242 if (NULL != update_func)
243 return update_func(work_object, force, recurse, update_parent);
245 return FALSE;
248 TMWorkObject *tm_work_object_find(TMWorkObject *work_object, const char *file_name
249 , gboolean name_only)
251 if ((NULL != work_object) && (work_object->type > 0) &&
252 (work_object->type < s_work_object_subclasses->len) &&
253 (s_work_object_subclasses->pdata[work_object->type] != NULL))
255 TMFindFunc find_func =
256 ((TMWorkObjectClass *)s_work_object_subclasses->pdata[work_object->type])->find_func;
257 if (NULL == find_func)
259 if (name_only)
261 const char *short_name = strrchr(file_name, '/');
262 if (short_name)
263 ++ short_name;
264 else
265 short_name = file_name;
266 if (0 == strcmp(work_object->short_name, short_name))
267 return work_object;
268 else
269 return NULL;
271 else
273 char *path = tm_get_real_path(file_name);
274 int cmp = strcmp(work_object->file_name, file_name);
275 g_free(path);
276 if (0 == cmp)
277 return work_object;
278 else
279 return NULL;
282 else
283 return find_func(work_object, file_name, name_only);
285 return NULL;
288 void tm_work_object_dump(const TMWorkObject *w)
290 if (w)
292 fprintf(stderr, "%s", w->file_name);
293 if (w->parent)
294 fprintf(stderr, " <- %s\n", w->parent->file_name);
295 else
296 fprintf(stderr, " <- NULL\n");