prgen.py fix
[geanyprj.git] / utils.c
blob267f8ef437ff9ee6c859bf1bdffbcbb8d0a4a9f9
1 /*
2 * geanyprj - Alternative project support for geany light IDE.
4 * Copyright 2008 Yura Siamashka <yurand2@gmail.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <string.h>
21 #include <glib.h>
23 #include "geany.h"
24 #include "plugindata.h"
25 #include "pluginmacros.h"
26 #include "utils.h"
28 extern GeanyData *geany_data;
31 gchar *
32 find_file_path(const gchar * dir, const gchar * filename)
34 gboolean ret = FALSE;
35 gchar *base;
36 gchar *gitdir = NULL;
37 gchar *base_prev = g_strdup(":");
39 base = g_strdup(dir);
41 while (strcmp(base, base_prev) != 0)
43 gitdir = g_build_path("/", base, filename, NULL);
44 ret = g_file_test(gitdir, G_FILE_TEST_IS_REGULAR);
45 if (ret)
47 g_free(base_prev);
48 g_free(base);
49 return gitdir;
51 g_free(gitdir);
52 g_free(base_prev);
53 base_prev = base;
54 base = g_path_get_dirname(base);
57 g_free(base_prev);
58 g_free(base);
59 return NULL;
62 /* Normalize a pathname. This collapses redundant separators and up-level references so that A//B, A/./B
63 * and A/foo/../B all become A/B. It does not normalize the case. On Windows, it converts forward
64 * slashes to backward slashes. It should be understood that this may change the meaning of the
65 * path if it contains symbolic links!
67 gchar *
68 normpath(const gchar * filename)
70 gchar **v;
71 gchar **p;
72 gchar **out;
73 gchar **pout;
74 gchar *ret;
76 if (!filename || strlen(filename) == 0)
77 return g_strdup(".");
78 v = g_strsplit_set(filename, "/\\", -1);
79 if (!g_strv_length(v))
80 return g_strdup(".");
82 out = g_malloc0(sizeof(gchar *) * (g_strv_length(v) + 2));
83 pout = out;
85 if (filename[0] == '.' && strcmp(v[0], ".") == 0)
87 *pout = strdup(".");
88 pout++;
90 else if (filename[0] == '/')
92 *pout = strdup("/");
93 pout++;
96 for (p = v; *p; p++)
98 if (strcmp(*p, ".") == 0 || strcmp(*p, "") == 0)
100 continue;
102 else if (strcmp(*p, "..") == 0)
104 if (pout != out)
106 pout--;
107 if (strcmp(*pout, "..") != 0)
109 g_free(*pout);
110 *pout = NULL;
111 continue;
113 pout++;
116 *pout++ = g_strdup(*p);
119 ret = g_build_filenamev(out);
121 g_strfreev(out);
122 g_strfreev(v);
123 return ret;
126 gchar *
127 get_full_path(const gchar * location, const gchar * path)
129 gchar *dir;
131 dir = g_path_get_dirname(location);
132 setptr(dir, g_build_filename(dir, path, NULL));
133 setptr(dir, normpath(dir));
134 return dir;
137 gchar *
138 get_relative_path(const gchar * location, const gchar * path)
140 gchar *dir;
141 gint plen;
142 gint dlen;
144 if (!g_path_is_absolute(path))
146 return g_strdup(path);
149 dir = g_path_get_dirname(location);
150 setptr(dir, normpath(dir));
152 plen = strlen(path);
153 dlen = strlen(dir);
155 if (strstr(path, dir) == path)
157 if (plen > dlen)
159 setptr(dir, g_strdup(path + strlen(dir) + 1));
160 return dir;
162 else if (plen == dlen)
164 return g_strdup("./");
167 g_free(dir);
168 return NULL;
171 void
172 save_config(GKeyFile * config, const gchar * path)
174 gchar *data = g_key_file_to_data(config, NULL, NULL);
175 p_utils->write_file(path, data);
176 g_free(data);
179 gint
180 config_length(GKeyFile * config, const gchar * section, const gchar * name)
182 gchar *key;
183 gint i = 0;
185 key = g_strdup_printf("%s%d", name, i);
186 while (g_key_file_has_key(config, section, key, NULL))
188 i++;
189 g_free(key);
190 key = g_strdup_printf("%s%d", name, i);
192 g_free(key);
193 return i;
197 /* Gets a list of files from the specified directory.
198 * Locale encoding is expected for path and used for the file list.
199 * The list and the data in the list should be freed after use.
200 * Returns: The list or NULL if no files found.
201 * length will point to the number of non-NULL data items in the list, unless NULL.
202 * error is the location for storing a possible error, or NULL. */
203 GSList *
204 get_file_list(const gchar * path, guint * length, gboolean(*func) (const gchar *), GError ** error)
206 GSList *list = NULL;
207 guint len = 0;
208 GDir *dir;
209 gchar *filename;
210 gchar *abs_path;
212 if (error)
213 *error = NULL;
214 if (length)
215 *length = 0;
216 g_return_val_if_fail(path != NULL, NULL);
218 if (g_path_is_absolute(path))
220 abs_path = g_strdup(path);
222 else
224 abs_path = g_get_current_dir();
225 setptr(abs_path, g_build_filename(abs_path, path, NULL));
227 if (!g_file_test(abs_path, G_FILE_TEST_IS_DIR))
229 g_free(abs_path);
230 return NULL;
233 dir = g_dir_open(abs_path, 0, error);
234 if (dir == NULL)
236 g_free(abs_path);
237 return NULL;
240 while (1)
242 const gchar *name = g_dir_read_name(dir);
243 if (name == NULL)
244 break;
246 filename = g_build_filename(abs_path, name, NULL);
248 if (g_file_test(filename, G_FILE_TEST_IS_DIR))
250 guint l;
251 GSList *lst = get_file_list(filename, &l, func, NULL);
252 g_free(filename);
253 if (!lst)
254 continue;
255 list = g_slist_concat(list, lst);
256 len += l;
258 else if (g_file_test(filename, G_FILE_TEST_IS_REGULAR))
260 if (!func || func(filename))
262 list = g_slist_prepend(list, filename);
263 len++;
265 else
267 g_free(filename);
271 g_dir_close(dir);
272 g_free(abs_path);
274 if (length)
275 *length = len;
276 return list;