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)  

filename_absolute.cxx

Go to the documentation of this file.
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 //