* lib/text.h: Added text_get_line() declaration
[dia.git] / lib / dia_dirs.c
blobdd89011b56d912b2d46fba8ff2544140a8fbd220
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <config.h>
21 #include <string.h> /* strlen() */
23 #include "dia_dirs.h"
24 #include "intl.h"
25 #include "message.h"
26 #ifdef G_OS_WIN32
27 #include <windows.h>
28 #include <direct.h>
29 #define mkdir(s,a) _mkdir(s)
30 #else
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #endif
35 /** Get the name of a subdirectory of our data directory.
36 * This function does not create the subdirectory, just make the correct name.
37 * @param subdir The name of the directory desired.
38 * @returns The full path to the directory. This string should be freed
39 * after use.
41 gchar *
42 dia_get_data_directory(const gchar* subdir)
44 #ifdef G_OS_WIN32
46 * Calculate from executable path
48 gchar sLoc [MAX_PATH+1];
49 HINSTANCE hInst = GetModuleHandle(NULL);
51 if (0 != GetModuleFileName(hInst, sLoc, MAX_PATH))
53 /* strip the name */
54 if (strrchr(sLoc, G_DIR_SEPARATOR))
55 strrchr(sLoc, G_DIR_SEPARATOR)[0] = 0;
56 /* and one dir (bin) */
57 if (strrchr(sLoc, G_DIR_SEPARATOR))
58 strrchr(sLoc, G_DIR_SEPARATOR)[1] = 0;
60 return g_strconcat (sLoc , subdir, NULL);
62 #else
63 if (strlen (subdir) == 0)
64 return g_strconcat (DIA_DATADIR, NULL);
65 else
66 return g_strconcat (DIA_DATADIR, G_DIR_SEPARATOR_S, subdir, NULL);
67 #endif
70 /** Get a subdirectory of our lib directory. This does not create the
71 * directory, merely the name of the full path.
72 * @param subdir The name of the subdirectory wanted.
73 * @returns The full path of the named directory. The string should be
74 * freed after use.
76 gchar*
77 dia_get_lib_directory(const gchar* subdir)
79 #ifdef G_OS_WIN32
81 * Calulate from executable path
83 gchar sLoc [MAX_PATH+1];
84 HINSTANCE hInst = GetModuleHandle(NULL);
86 if (0 != GetModuleFileName(hInst, sLoc, MAX_PATH))
88 /* strip the name */
89 if (strrchr(sLoc, G_DIR_SEPARATOR))
90 strrchr(sLoc, G_DIR_SEPARATOR)[0] = 0;
91 /* and one dir (bin) */
92 if (strrchr(sLoc, G_DIR_SEPARATOR))
93 strrchr(sLoc, G_DIR_SEPARATOR)[1] = 0;
95 return g_strconcat (sLoc , subdir, NULL);
97 #else
98 return g_strconcat (DIA_LIBDIR, G_DIR_SEPARATOR_S, subdir, NULL);
99 #endif
102 /** Get the name of a file under the Dia config directory. If no home
103 * directory can be found, uses a temporary directory.
104 * @param subfile Name of the subfile.
105 * @returns A string with the full path of the desired file. This string
106 * should be freed after use.
108 gchar *
109 dia_config_filename(const gchar *subfile)
111 const gchar *homedir;
113 homedir = g_get_home_dir();
114 if (!homedir) {
115 homedir = g_get_tmp_dir(); /* put config stuff in /tmp -- not ideal, but
116 * we should not reach this state */
118 return g_strconcat(homedir, G_DIR_SEPARATOR_S ".dia" G_DIR_SEPARATOR_S,
119 subfile, NULL);
122 /** Ensure that the directory part of `filename' exists.
123 * @param filename A file that we want the parent directory of to exist.
124 * @returns TRUE if the directory existed or has been created, FALSE if
125 * it cannot be created.
127 gboolean
128 dia_config_ensure_dir(const gchar *filename)
130 gchar *dir = g_path_get_dirname(filename);
131 gboolean exists;
132 if (dir == NULL) return FALSE;
133 if (strcmp(dir, ".")) {
134 if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
135 exists = TRUE;
136 } else {
137 if (dia_config_ensure_dir(dir)) {
138 exists = (mkdir(dir, 0755) == 0);
139 } else {
140 exists = FALSE;
143 } else {
144 exists = FALSE;
146 g_free(dir);
147 return exists;
150 /** Remove all instances of . and .. from an absolute path.
151 * This is not a cheap function.
152 * @param path String to canonicalize.
153 * @returns A newly allocated string, or NULL if too many ..'s were found
155 static gchar *
156 dia_get_canonical_path(const gchar *path)
158 gchar *ret = NULL;
159 gchar **list = g_strsplit (path, G_DIR_SEPARATOR_S, -1);
160 int i = 0, n = 0;
162 while (list[i] != NULL) {
163 if (0 == strcmp (list[i], ".")) {
164 /* simple, just remove it */
165 g_free (list[i]);
166 list[i] = g_strdup ("");
168 else if (0 == strcmp (list[i], "..")) {
169 /* need to 'remove' the previous non empty part too */
170 n = i;
171 g_free (list[i]);
172 list[i] = g_strdup ("");
173 while (n >= 0) {
174 if (0 != strlen(list[n])) {
175 /* remove it */
176 g_free (list[n]);
177 list[n] = g_strdup ("");
178 break;
180 n--;
182 /* we haven't found an entry to remove for '..' */
183 if (n < 0)
184 break;
186 i++;
188 if (n >= 0) {
189 /* cant use g_strjoinv () cause it would stumble about empty elements */
190 GString *str = g_string_new (NULL);
192 i = 0;
193 while (list[i] != NULL) {
194 if (strlen(list[i]) > 0) {
196 /* win32 filenames usually don't start with a dir separator but
197 * with <drive>:\
199 if (i != 0 || list[i][1] != ':')
200 g_string_append (str, G_DIR_SEPARATOR_S);
201 g_string_append (str, list[i]);
203 i++;
205 ret = g_string_free (str, FALSE);
208 g_strfreev(list);
210 return ret;
213 /** Returns an filename in UTF-8 encoding from filename in filesystem
214 * encoding. In GTK < 2.6, invalid sequences are not [???]
215 * @param filename A filename string as gotten from the filesystem.
216 * @returns UTF-8 encoded copy of the filename.
217 * The value returned is a pointer to static array.
218 * Note: The string can be used AFTER the next call to this function
219 * Written like glib/gstrfuncs.c#g_strerror()
221 const gchar *
222 dia_message_filename(const gchar *filename)
224 gchar *tmp;
225 GQuark msg_quark;
227 #if GLIB_CHECK_VERSION(2,6,0)
228 tmp = g_filename_display_name(filename);
229 #else
230 gsize num_read;
231 tmp = g_filename_to_utf8(filename, -1, &num_read, NULL, NULL);
232 if (tmp == NULL) {
233 gchar *ellipsis;
234 /* Best effort at displaying filename: Display as must as is readable */
235 g_utf8_validate(filename, -1, &ellipsis);
236 tmp = g_filename_to_utf8(filename, ellipsis-filename, NULL, NULL, NULL);
237 ellipsis = g_strdup_printf(_("%s<illegal characters>..."), tmp);
238 g_free(tmp);
239 tmp = ellipsis;
241 #endif
242 /* Stick in the quark table so that we can return a static result
244 msg_quark = g_quark_from_string (tmp);
245 g_free (tmp);
246 tmp = (gchar *) g_quark_to_string (msg_quark);
247 return tmp;
250 /** Return an absolute filename from an absolute or relative filename.
251 * @param filename A relative or absolute filename.
252 * @return Absolute and canonicalized filename as a newly allocated string.
254 gchar *
255 dia_get_absolute_filename (const gchar *filename)
257 gchar *current_dir;
258 gchar *fullname;
259 gchar *canonical;
260 if (filename == NULL) return NULL;
261 if (g_path_is_absolute(filename)) return dia_get_canonical_path(filename);
262 current_dir = g_get_current_dir();
263 fullname = g_build_filename(current_dir, filename, NULL);
264 g_free(current_dir);
265 if (strchr(fullname, '.') == NULL) return fullname;
266 canonical = dia_get_canonical_path(fullname);
267 if (canonical == NULL) {
268 message_warning(_("Too many ..'s in filename %s\n"),
269 dia_message_filename(filename));
270 return g_strdup(filename);
272 g_free(fullname);
273 return canonical;