2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
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 2 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Code that is independent of any other Viking specific types
23 * Otherwise see file.c
29 #include "fileutils.h"
33 #define realpath(X,Y) _fullpath(Y,X,MAX_PATH)
39 const gchar *a_file_basename ( const gchar *filename )
41 const gchar *t = filename + strlen(filename) - 1;
42 while ( --t > filename )
43 if ( *(t-1) == FILE_SEP )
51 * Just a wrapper around realpath, which itself is platform dependent
53 char *file_realpath ( const char *path, char *real )
55 return realpath ( path, real );
59 #define MAXPATHLEN 1024
62 * Always return the canonical filename in a newly allocated string
64 char *file_realpath_dup ( const char *path )
66 char real[MAXPATHLEN];
68 g_return_val_if_fail(path != NULL, NULL);
70 if (file_realpath(path, real))
71 return g_strdup(real);
73 return g_strdup(path);
77 * Permission granted to use this code after personal correspondance
78 * Slightly reworked for better cross platform use, glibisms, function rename and a compacter format
80 * FROM http://www.codeguru.com/cpp/misc/misc/fileanddirectorynaming/article.php/c263
83 // GetRelativeFilename(), by Rob Fisher.
85 // http://come.to/robfisher
87 // The number of characters at the start of an absolute filename. e.g. in DOS,
88 // absolute filenames start with "X:\" so this value should be 3, in UNIX they start
89 // with "\" so this value should be 1.
91 #define ABSOLUTE_NAME_START 3
93 #define ABSOLUTE_NAME_START 1
96 // Given the absolute current directory and an absolute file name, returns a relative file name.
97 // For example, if the current directory is C:\foo\bar and the filename C:\foo\whee\text.txt is given,
98 // GetRelativeFilename will return ..\whee\text.txt.
100 const gchar *file_GetRelativeFilename ( gchar *currentDirectory, gchar *absoluteFilename )
102 gint afMarker = 0, rfMarker = 0;
103 gint cdLen = 0, afLen = 0;
106 static gchar relativeFilename[MAXPATHLEN+1];
108 cdLen = strlen(currentDirectory);
109 afLen = strlen(absoluteFilename);
111 // make sure the names are not too long or too short
112 if (cdLen > MAXPATHLEN || cdLen < ABSOLUTE_NAME_START+1 ||
113 afLen > MAXPATHLEN || afLen < ABSOLUTE_NAME_START+1) {
117 // Handle DOS names that are on different drives:
118 if (currentDirectory[0] != absoluteFilename[0]) {
119 // not on the same drive, so only absolute filename will do
120 g_strlcpy(relativeFilename, absoluteFilename, MAXPATHLEN+1);
121 return relativeFilename;
124 // they are on the same drive, find out how much of the current directory
125 // is in the absolute filename
126 i = ABSOLUTE_NAME_START;
127 while (i < afLen && i < cdLen && currentDirectory[i] == absoluteFilename[i]) {
131 if (i == cdLen && (absoluteFilename[i] == G_DIR_SEPARATOR || absoluteFilename[i-1] == G_DIR_SEPARATOR)) {
132 // the whole current directory name is in the file name,
133 // so we just trim off the current directory name to get the
134 // current file name.
135 if (absoluteFilename[i] == G_DIR_SEPARATOR) {
136 // a directory name might have a trailing slash but a relative
137 // file name should not have a leading one...
141 g_strlcpy(relativeFilename, &absoluteFilename[i], MAXPATHLEN+1);
142 return relativeFilename;
145 // The file is not in a child directory of the current directory, so we
146 // need to step back the appropriate number of parent directories by
147 // using "..\"s. First find out how many levels deeper we are than the
152 // count the number of directory levels we have to go up to get to the
156 if (currentDirectory[i] == G_DIR_SEPARATOR) {
157 // make sure it's not a trailing slash
159 if (currentDirectory[i] != '\0') {
165 // move the absolute filename marker back to the start of the directory name
166 // that it has stopped in.
167 while (afMarker > 0 && absoluteFilename[afMarker-1] != G_DIR_SEPARATOR) {
171 // check that the result will not be too long
172 if (levels * 3 + afLen - afMarker > MAXPATHLEN) {
176 // add the appropriate number of "..\"s.
178 for (i = 0; i < levels; i++) {
179 relativeFilename[rfMarker++] = '.';
180 relativeFilename[rfMarker++] = '.';
181 relativeFilename[rfMarker++] = G_DIR_SEPARATOR;
184 // copy the rest of the filename into the result string
185 strcpy(&relativeFilename[rfMarker], &absoluteFilename[afMarker]);
187 return relativeFilename;
189 /* END http://www.codeguru.com/cpp/misc/misc/fileanddirectorynaming/article.php/c263 */