|  | @@ -1130,6 +1130,29 @@ kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
 | 
	
		
			
				|  |  |    return n;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +//----------------------------------------------------------------------------
 | 
	
		
			
				|  |  | +std::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  std::string path = p;
 | 
	
		
			
				|  |  | +  std::vector<kwsys::String> paths;
 | 
	
		
			
				|  |  | +  if(isPath && path[0] == '/')
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    path.erase(path.begin());
 | 
	
		
			
				|  |  | +    paths.push_back("/"); 
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  std::string::size_type pos1 = 0;
 | 
	
		
			
				|  |  | +  std::string::size_type pos2 = path.find(sep, pos1+1);
 | 
	
		
			
				|  |  | +  while(pos2 != std::string::npos)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    paths.push_back(path.substr(pos1, pos2-pos1));
 | 
	
		
			
				|  |  | +    pos1 = pos2+1;
 | 
	
		
			
				|  |  | +    pos2 = path.find(sep, pos1+1);
 | 
	
		
			
				|  |  | +    } 
 | 
	
		
			
				|  |  | +  paths.push_back(path.substr(pos1, pos2-pos1));
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  return paths;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  //----------------------------------------------------------------------------
 | 
	
		
			
				|  |  |  int SystemTools::EstimateFormatLength(const char *format, va_list ap)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -2395,6 +2418,85 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
 | 
	
		
			
				|  |  |    return newPath;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// compute the relative path from here to there
 | 
	
		
			
				|  |  | +std::string SystemTools::RelativePath(const char* local, const char* remote)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  if(!SystemTools::FileIsFullPath(local))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    return "";
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  if(!SystemTools::FileIsFullPath(remote))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    return "";
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  // split up both paths into arrays of strings using / as a separator
 | 
	
		
			
				|  |  | +  std::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true); 
 | 
	
		
			
				|  |  | +  std::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
 | 
	
		
			
				|  |  | +  std::vector<kwsys::String> commonPath; // store shared parts of path in this array
 | 
	
		
			
				|  |  | +  std::vector<kwsys::String> finalPath;  // store the final relative path here
 | 
	
		
			
				|  |  | +  // count up how many matching directory names there are from the start
 | 
	
		
			
				|  |  | +  unsigned int sameCount = 0;
 | 
	
		
			
				|  |  | +  while(
 | 
	
		
			
				|  |  | +    ((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
 | 
	
		
			
				|  |  | +    && 
 | 
	
		
			
				|  |  | +// for windows and apple do a case insensitive string compare    
 | 
	
		
			
				|  |  | +#if defined(_WIN32) || defined(__APPLE__)
 | 
	
		
			
				|  |  | +    cmSystemTools::Strucmp(localSplit[sameCount].c_str(),
 | 
	
		
			
				|  |  | +                           remoteSplit[sameCount].c_str()) == 0
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +    localSplit[sameCount] == remoteSplit[sameCount]
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    // put the common parts of the path into the commonPath array
 | 
	
		
			
				|  |  | +    commonPath.push_back(localSplit[sameCount]);
 | 
	
		
			
				|  |  | +    // erase the common parts of the path from the original path arrays
 | 
	
		
			
				|  |  | +    localSplit[sameCount] = "";
 | 
	
		
			
				|  |  | +    remoteSplit[sameCount] = "";
 | 
	
		
			
				|  |  | +    sameCount++;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  // If there is nothing in common but the root directory, then just
 | 
	
		
			
				|  |  | +  // return the full path.
 | 
	
		
			
				|  |  | +  if(sameCount <= 1)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    return remote;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  // for each entry that is not common in the local path
 | 
	
		
			
				|  |  | +  // add a ../ to the finalpath array, this gets us out of the local
 | 
	
		
			
				|  |  | +  // path into the remote dir
 | 
	
		
			
				|  |  | +  for(unsigned int i = 0; i < localSplit.size(); ++i)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    if(localSplit[i].size())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      finalPath.push_back("../");
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  // for each entry that is not common in the remote path add it
 | 
	
		
			
				|  |  | +  // to the final path.
 | 
	
		
			
				|  |  | +  for(std::vector<kwsys_stl::string>::iterator i = remoteSplit.begin();
 | 
	
		
			
				|  |  | +      i != remoteSplit.end(); ++i)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    if(i->size())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      finalPath.push_back(*i);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  std::string relativePath;     // result string
 | 
	
		
			
				|  |  | +  // now turn the array of directories into a unix path by puttint / 
 | 
	
		
			
				|  |  | +  // between each entry that does not already have one
 | 
	
		
			
				|  |  | +  for(std::vector<kwsys_stl::string>::iterator i = finalPath.begin();
 | 
	
		
			
				|  |  | +      i != finalPath.end(); ++i)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      relativePath += "/";
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    relativePath += *i;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  return relativePath;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // OK, some fun stuff to get the actual case of a given path.
 | 
	
		
			
				|  |  |  // Basically, you just need to call ShortPath, then GetLongPathName,
 |