|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: filename_absolute.cxx 8146 2010-12-31 22:13:07Z matt $" 00003 // 00004 // Filename expansion routines for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 /* expand a file name by prepending current directory, deleting . and 00029 .. (not really correct for symbolic links) between the prepended 00030 current directory. Use $PWD if it exists. 00031 Returns true if any changes were made. 00032 */ 00033 00034 #include <FL/filename.H> 00035 #include <FL/fl_utf8.h> 00036 #include <stdlib.h> 00037 #include "flstring.h" 00038 #include <ctype.h> 00039 #if defined(WIN32) && !defined(__CYGWIN__) 00040 # include <direct.h> 00041 #else 00042 # include <unistd.h> 00043 #endif 00044 00045 #if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) 00046 inline int isdirsep(char c) {return c=='/' || c=='\\';} 00047 #else 00048 #define isdirsep(c) ((c)=='/') 00049 #endif 00050 00065 int fl_filename_absolute(char *to, int tolen, const char *from) { 00066 if (isdirsep(*from) || *from == '|' 00067 #if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) 00068 || from[1]==':' 00069 #endif 00070 ) { 00071 strlcpy(to, from, tolen); 00072 return 0; 00073 } 00074 00075 char *a; 00076 char *temp = new char[tolen]; 00077 const char *start = from; 00078 00079 a = fl_getcwd(temp, tolen); 00080 if (!a) { 00081 strlcpy(to, from, tolen); 00082 delete[] temp; 00083 return 0; 00084 } 00085 #if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) 00086 for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha 00087 #else 00088 a = temp+strlen(temp); 00089 #endif 00090 if (isdirsep(*(a-1))) a--; 00091 /* remove intermediate . and .. names: */ 00092 while (*start == '.') { 00093 if (start[1]=='.' && isdirsep(start[2])) { 00094 char *b; 00095 for (b = a-1; b >= temp && !isdirsep(*b); b--); 00096 if (b < temp) break; 00097 a = b; 00098 start += 3; 00099 } else if (isdirsep(start[1])) { 00100 start += 2; 00101 } else if (!start[1]) { 00102 start ++; // Skip lone "." 00103 break; 00104 } else 00105 break; 00106 } 00107 00108 *a++ = '/'; 00109 strlcpy(a,start,tolen - (a - temp)); 00110 00111 strlcpy(to, temp, tolen); 00112 00113 delete[] temp; 00114 00115 return 1; 00116 } 00117 00136 int // O - 0 if no change, 1 if changed 00137 fl_filename_relative(char *to, // O - Relative filename 00138 int tolen, // I - Size of "to" buffer 00139 const char *from) // I - Absolute filename 00140 { 00141 char cwd_buf[FL_PATH_MAX]; // Current directory 00142 // get the current directory and return if we can't 00143 if (!fl_getcwd(cwd_buf, sizeof(cwd_buf))) { 00144 strlcpy(to, from, tolen); 00145 return 0; 00146 } 00147 return fl_filename_relative(to, tolen, from, cwd_buf); 00148 } 00149 00150 00158 int // O - 0 if no change, 1 if changed 00159 fl_filename_relative(char *to, // O - Relative filename 00160 int tolen, // I - Size of "to" buffer 00161 const char *from, // I - Absolute filename 00162 const char *base) { // I - Find path relative to this path 00163 00164 char *newslash; // Directory separator 00165 const char *slash; // Directory separator 00166 char *cwd = 0L, *cwd_buf = 0L; 00167 if (base) cwd = cwd_buf = strdup(base); 00168 00169 // return if "from" is not an absolute path 00170 #if defined(WIN32) || defined(__EMX__) 00171 if (from[0] == '\0' || 00172 (!isdirsep(*from) && !isalpha(*from) && from[1] != ':' && 00173 !isdirsep(from[2]))) { 00174 #else 00175 if (from[0] == '\0' || !isdirsep(*from)) { 00176 #endif // WIN32 || __EMX__ 00177 strlcpy(to, from, tolen); 00178 if (cwd_buf) free(cwd_buf); 00179 return 0; 00180 } 00181 00182 // return if "cwd" is not an absolute path 00183 #if defined(WIN32) || defined(__EMX__) 00184 if (!cwd || cwd[0] == '\0' || 00185 (!isdirsep(*cwd) && !isalpha(*cwd) && cwd[1] != ':' && 00186 !isdirsep(cwd[2]))) { 00187 #else 00188 if (!cwd || cwd[0] == '\0' || !isdirsep(*cwd)) { 00189 #endif // WIN32 || __EMX__ 00190 strlcpy(to, from, tolen); 00191 if (cwd_buf) free(cwd_buf); 00192 return 0; 00193 } 00194 00195 #if defined(WIN32) || defined(__EMX__) 00196 // convert all backslashes into forward slashes 00197 for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\')) 00198 *newslash = '/'; 00199 00200 // test for the exact same string and return "." if so 00201 if (!strcasecmp(from, cwd)) { 00202 strlcpy(to, ".", tolen); 00203 free(cwd_buf); 00204 return (1); 00205 } 00206 00207 // test for the same drive. Return the absolute path if not 00208 if (tolower(*from & 255) != tolower(*cwd & 255)) { 00209 // Not the same drive... 00210 strlcpy(to, from, tolen); 00211 free(cwd_buf); 00212 return 0; 00213 } 00214 00215 // compare the path name without the drive prefix 00216 from += 2; cwd += 2; 00217 #else 00218 // test for the exact same string and return "." if so 00219 if (!strcmp(from, cwd)) { 00220 strlcpy(to, ".", tolen); 00221 free(cwd_buf); 00222 return (1); 00223 } 00224 #endif // WIN32 || __EMX__ 00225 00226 // compare both path names until we find a difference 00227 for (slash = from, newslash = cwd; 00228 *slash != '\0' && *newslash != '\0'; 00229 slash ++, newslash ++) 00230 if (isdirsep(*slash) && isdirsep(*newslash)) continue; 00231 #if defined(WIN32) || defined(__EMX__) || defined(__APPLE__) 00232 else if (tolower(*slash & 255) != tolower(*newslash & 255)) break; 00233 #else 00234 else if (*slash != *newslash) break; 00235 #endif // WIN32 || __EMX__ || __APPLE__ 00236 00237 // skip over trailing slashes 00238 if ( *newslash == '\0' && *slash != '\0' && !isdirsep(*slash) 00239 &&(newslash==cwd || !isdirsep(newslash[-1])) ) 00240 newslash--; 00241 00242 // now go back to the first character of the first differing paths segment 00243 while (!isdirsep(*slash) && slash > from) slash --; 00244 if (isdirsep(*slash)) slash ++; 00245 00246 // do the same for the current dir 00247 if (isdirsep(*newslash)) newslash --; 00248 if (*newslash != '\0') 00249 while (!isdirsep(*newslash) && newslash > cwd) newslash --; 00250 00251 // prepare the destination buffer 00252 to[0] = '\0'; 00253 to[tolen - 1] = '\0'; 00254 00255 // now add a "previous dir" sequence for every following slash in the cwd 00256 while (*newslash != '\0') { 00257 if (isdirsep(*newslash)) strlcat(to, "../", tolen); 00258 00259 newslash ++; 00260 } 00261 00262 // finally add the differing path from "from" 00263 strlcat(to, slash, tolen); 00264 00265 free(cwd_buf); 00266 return 1; 00267 } 00268 00269 00270 // 00271 // End of "$Id: filename_absolute.cxx 8146 2010-12-31 22:13:07Z matt $". 00272 //