1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Luc BILLARD et Damien
3 CALISTE, laboratoire L_Sim, (2001-2005)
4
5 Adresse mèl :
6 BILLARD, non joignable par mèl ;
7 CALISTE, damien P caliste AT cea P fr.
8
9 Ce logiciel est un programme informatique servant à visualiser des
10 structures atomiques dans un rendu pseudo-3D.
11
12 Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 respectant les principes de diffusion des logiciels libres. Vous pouvez
14 utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 sur le site "http://www.cecill.info".
17
18 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22
23 /* LICENCE SUM UP
24 Copyright CEA, contributors : Luc BILLARD et Damien
25 CALISTE, laboratoire L_Sim, (2001-2005)
26
27 E-mail address:
28 BILLARD, not reachable any more ;
29 CALISTE, damien P caliste AT cea P fr.
30
31 This software is a computer program whose purpose is to visualize atomic
32 configurations in 3D.
33
34 This software is governed by the CeCILL license under French law and
35 abiding by the rules of distribution of free software. You can use,
36 modify and/ or redistribute the software under the terms of the CeCILL
37 license as circulated by CEA, CNRS and INRIA at the following URL
38 "http://www.cecill.info".
39
40 The fact that you are presently reading this means that you have had
41 knowledge of the CeCILL license and that you accept its terms. You can
42 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 #include "visu_tools.h"
45
46 #include <string.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <unistd.h> /* For the access markers R_OK, W_OK ... */
50 #include <math.h>
51
52 /**
53 * tool_getValidPath:
54 * @pathList: (element-type filename): a pointer to a GList with all the possible path,
55 * @filenames: (array zero-terminated=1) (element-type filename): an array of strings,
56 * @accessMode: a value from R_OK, W_OK and X_OK as described in unistd.h.
57 *
58 * @pathList contains a list of directories (first is most prefered)
59 * and fileName is the file name which one likes have informations on. This routine
60 * look for the first directory where fileName can be writen or read (depending
61 * on accessMode parameter). The pointer to the GList indicates at the end the
62 * first valid entry in the GList.
63 *
64 * Returns: (transfer full): the first valid complete path (from
65 * @pathList plus an entry of @filenames) if one can be found depnding
66 * on @accessMode or NULL if none found. Free it with g_free() after
67 * use.
68 */
tool_getValidPath(GList ** pathList,const char ** filenames,int accessMode)69 gchar* tool_getValidPath(GList **pathList, const char **filenames, int accessMode)
70 {
71 gchar *validPath;
72 int fileOk;
73 guint i;
74
75 g_return_val_if_fail(pathList && filenames, (gchar*)0);
76
77 DBG_fprintf(stderr, "Visu Tools : test access (%d) from list of %d elements.\n",
78 accessMode, g_list_length(*pathList));
79 validPath = (char*)0;
80 /* look for a directory to save or read a file. */
81 fileOk = 0;
82 while (*pathList && !fileOk)
83 {
84 for (i = 0; filenames[i]; i++)
85 {
86 validPath = g_build_filename((gchar*)(*pathList)->data, filenames[i], NULL);
87 DBG_fprintf(stderr, "Visu Tools : test access (%d) for '%s' ... ",
88 accessMode, validPath);
89 fileOk = !access((char*)validPath, accessMode); /* return 0 if success */
90 if (fileOk)
91 break;
92
93 /* if access mode is write access and the file does not already exist :
94 we test if the directory has written permitions. */
95 if ( accessMode == W_OK && !g_file_test(validPath, G_FILE_TEST_EXISTS) )
96 fileOk = !access((char*)(*pathList)->data, accessMode);
97
98 if (fileOk)
99 break;
100
101 DBG_fprintf(stderr, " failed.\n");
102 g_free(validPath);
103 }
104 if (!fileOk)
105 *pathList = g_list_next(*pathList);
106 }
107 if (fileOk)
108 {
109 DBG_fprintf(stderr, " OK.\n");
110 return validPath;
111 }
112 else
113 return (gchar*)0;
114 }
115
116 /**
117 * tool_modulo_float:
118 * @a: a float ;
119 * @b: an int.
120 *
121 * This function is just like a%b except it works with a float @a argument.
122 * @a can be negative, but the return value of the function is always positive.
123 *
124 * Returns: the new float value after the modulo.
125 */
tool_modulo_float(float a,int b)126 float tool_modulo_float(float a, int b) {
127 float fb = (float)b;
128 while(a < fb) a += fb;
129 while(a >= fb) a -= fb;
130 return a;
131 }
132
133 /**
134 * tool_path_normalize:
135 * @path: a string, NULL terminated.
136 *
137 * This function normalizes the path, i.e. it removes all . and .. It should
138 * work also on Windows. It must take an absolute path as argument, if not it is converted
139 * assuming the current working directory.
140 *
141 * Returns: a newly created string.
142 */
tool_path_normalize(const gchar * path)143 gchar* tool_path_normalize(const gchar* path)
144 {
145 #if SYSTEM_X11 == 1
146 #define FILE_SYSTEM_SEP "/"
147 #endif
148 #if SYSTEM_WIN32 == 1
149 #define FILE_SYSTEM_SEP "\\"
150 #endif
151 gchar **tokens;
152 int i;
153 GString *normPath;
154 GList *lst, *tmplst;
155 gchar *allPath, *dir;
156
157 if (!path)
158 return (gchar*)0;
159
160 if (!g_path_is_absolute(path))
161 {
162 dir = g_get_current_dir();
163 allPath = g_build_filename(dir, path, NULL);
164 g_free(dir);
165 }
166 else
167 allPath = g_strdup(path);
168
169 tokens = g_strsplit(allPath, FILE_SYSTEM_SEP, -1);
170
171 normPath = g_string_new("");
172
173 lst = (GList*)0;
174 for (i = 0; tokens[i]; i++)
175 {
176 /* If tokens[i] == . or is empty (because of //), we ignore. */
177 if (!strcmp(tokens[i], "."))
178 continue;
179 if (!tokens[i][0])
180 continue;
181 /* If token[i] == .. then we pop one element from lst. */
182 if (!strcmp(tokens[i], ".."))
183 {
184 lst = g_list_delete_link(lst, lst);
185 continue;
186 }
187 /* Token[i] is a valid chain, then we prepend it to the list. */
188 lst = g_list_prepend(lst, tokens[i]);
189 }
190 /* Write the lst to the string. */
191 for (tmplst = lst; tmplst; tmplst = g_list_next(tmplst))
192 {
193 g_string_prepend(normPath, (gchar*)tmplst->data);
194 g_string_prepend(normPath, FILE_SYSTEM_SEP);
195 }
196 g_list_free(lst);
197 #if SYSTEM_WIN32 == 1
198 g_string_erase(normPath, 0,1);
199 #endif
200 g_strfreev(tokens);
201 g_free(allPath);
202 if (!normPath->str[0])
203 g_string_append(normPath, FILE_SYSTEM_SEP);
204 DBG_fprintf(stderr, "Visu Tools : normalizing path, from '%s' to '%s'.\n",
205 path, normPath->str);
206 return g_string_free(normPath, FALSE);
207 }
208
209 #if GLIB_MINOR_VERSION < 5
210 /**
211 * g_file_set_contents:
212 * @fileName: a string ;
213 * @str: a string ;
214 * @len: a length or -1 ;
215 * @error: a location for an error.
216 *
217 * Compiled only if Glib is lower than 2.5.
218 *
219 * Returns: TRUE on success.
220 */
g_file_set_contents(const gchar * fileName,const gchar * str,gsize len _U_,GError ** error _U_)221 gboolean g_file_set_contents(const gchar *fileName, const gchar *str,
222 gsize len _U_, GError **error _U_)
223 {
224 FILE *f;
225
226 f = fopen(fileName, "w");
227 if (!f)
228 return FALSE;
229 if (fwrite(str, strlen(str), 1, f) != strlen(str))
230 return FALSE;
231 fclose(f);
232
233 return TRUE;
234 }
235 #endif
236 #if GLIB_MINOR_VERSION < 27
237 /**
238 * g_list_free_full:
239 * @list: a pointer to a #GList
240 * @free_func: the function to be called to free each element's data
241 *
242 * Convenience method, which frees all the memory used by a #GList, and
243 * calls the specified destroy function on every element's data.
244 *
245 * Compiled only if Glib is lower than 2.27.
246 */
247 void
g_list_free_full(GList * list,GDestroyNotify free_func)248 g_list_free_full (GList *list,
249 GDestroyNotify free_func)
250 {
251 g_list_foreach (list, (GFunc) free_func, NULL);
252 g_list_free (list);
253 }
254 #endif
255
tagLookup(const gchar * tag,const gchar * buffer)256 static gchar* tagLookup(const gchar *tag, const gchar *buffer)
257 {
258 char *ptTag, *ptStart, *ptEnd;
259
260 ptTag = strstr(buffer, tag);
261 if (!ptTag)
262 return (gchar*)0;
263
264 /* We check that tag was not in a commentary section. */
265 ptStart = g_strrstr_len(buffer, (gssize)(ptTag - buffer), "<!--");
266 if (!ptStart)
267 return ptTag;
268 ptEnd = g_strstr_len(ptStart, (gssize)(ptTag - ptStart), "-->");
269 if (ptEnd)
270 return ptTag;
271 return tagLookup(tag, ptTag + strlen(tag));
272 }
273 /**
274 * tool_XML_substitute:
275 * @output: a GString to store the substitution ;
276 * @filename: the file to read the data from ;
277 * @tag: the tag to substitute ;
278 * @error: a location to store possible errors.
279 *
280 * Read @filename (must be XML file) and remove the @tag zone from
281 * it. At that place, it puts the contain of @output.
282 *
283 * Returns: TRUE if no error occured.
284 */
tool_XML_substitute(GString * output,const gchar * filename,const gchar * tag,GError ** error)285 gboolean tool_XML_substitute(GString *output, const gchar *filename,
286 const gchar *tag, GError **error)
287 {
288 gchar *contents, *ptStart, *ptStop;
289 gchar *tgStart, *tgEnd;
290 gboolean valid;
291
292 /* If file does exist, we read it and replace only the tag part. */
293 contents = (gchar*)0;
294 ptStart = (gchar*)0;
295 if (g_file_test(filename, G_FILE_TEST_EXISTS))
296 {
297 valid = g_file_get_contents(filename, &contents, (gsize*)0, error);
298 if (!valid)
299 return FALSE;
300
301 tgStart = g_strdup_printf("<%s", tag);
302
303 ptStart = tagLookup(tgStart, contents);
304 if (ptStart)
305 g_string_prepend_len(output, contents, (gssize)(ptStart - contents));
306 else
307 {
308 g_string_prepend(output, " ");
309 ptStop = tagLookup("</v_sim>", contents);
310 if (ptStop)
311 g_string_prepend_len(output, contents, (gssize)(ptStop - contents));
312 else
313 {
314 ptStop = tagLookup("<v_sim>", contents);
315 if (ptStop)
316 g_string_prepend(output, contents);
317 else
318 {
319 g_string_prepend(output, contents);
320 g_string_prepend(output, "<?xml version=\"1.0\""
321 " encoding=\"utf-8\"?>\n<v_sim>");
322 }
323 }
324 }
325
326 g_free(tgStart);
327 }
328 else
329 g_string_prepend(output, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<v_sim>\n ");
330
331 /* If file does exist, we add the remaining parts. */
332 if (contents && ptStart)
333 {
334 tgEnd = g_strdup_printf("</%s>", tag);
335
336 ptStop = tagLookup(tgEnd, ptStart);
337 if (ptStop)
338 g_string_append(output, ptStop + strlen(tgEnd));
339 else
340 g_string_append(output, "\n</v_sim>");
341
342 g_free(tgEnd);
343 }
344 else
345 g_string_append(output, "</v_sim>\n");
346
347 if (contents)
348 g_free(contents);
349
350 return TRUE;
351 }
352