[quoted text, click to view] Andrew Chalk wrote:
> Is their any built-in Win32 function that returns the relative path to a
> file given the applications current working directory?
>
> Many thanks
Andrew, I quickly pulled some "path" related c/c++ functions from my
pathlib.cpp library, and put this test demo "Relative.cpp" example.
Hope this helps
--
HLS
// File: V:\local\wc5\common\relative.cpp
// comple: CL relative.cpp" /W3 /GX /MD /D "_AFXDLL"
#include <stdio.h>
#include <afx.h>
typedef struct _SPLITFILEPARTS {
char drive[_MAX_DRIVE]; // WIN32 defines this as 3
char dir[_MAX_DIR]; // WIN32 defines this as 256
char fname[_MAX_FNAME]; // WIN32 defines this as 256
char ext[_MAX_EXT]; // WIN32 defines this as 256
} SPLITFILEPARTS, *PSLITFILEPATHS;
char *ExtractFilePath(char *dest, const char *s,
const BOOL noDrive = FALSE);
char *ExtractFileName(char *dest, const char *s,
const BOOL noExt = FALSE);
BOOL ExtractFileParts(const char *s, SPLITFILEPARTS &sf)
{
ZeroMemory(&sf,sizeof(sf));
if (s == NULL) return FALSE;
_splitpath(s, sf.drive, sf.dir, sf.fname,sf.ext);
return TRUE;
}
char *ExtractFileName(char *dest, const char *s,
const BOOL noExt /* = FALSE */)
{
SPLITFILEPARTS sf;
if (!ExtractFileParts(s,sf)) return dest;
if (noExt) sf.ext[0] = 0;
_makepath(dest,"","",sf.fname,sf.ext);
return dest;
}
CString ExtractFileName(const char *s)
{
CString q;
char *p = q.GetBuffer(MAX_PATH);
ExtractFileName(p, s);
q.ReleaseBuffer();
return q;
}
char *ExtractFilePath(char *dest, const char *s,
const BOOL noDrive /* = FALSE */)
{
SPLITFILEPARTS sf;
if (!ExtractFileParts(s,sf)) return dest;
if (noDrive) sf.drive[0] = 0;
_makepath(dest,sf.drive,sf.dir,"","");
return dest;
}
CString ExtractFilePath(const char *s)
{
CString q;
char *p = q.GetBuffer(MAX_PATH);
ExtractFilePath(p, s);
q.ReleaseBuffer();
return q;
}
CString ExtractFileDrive(const char *s)
{
if (s == NULL) {
return "";
}
CString q;
char *p = q.GetBuffer(MAX_PATH);
SPLITFILEPARTS sf;
ExtractFileParts(s,sf);
_makepath(p, sf.drive,"","","");
q.ReleaseBuffer();
return q;
}
CString ExtractFilePathNoDrive(const char *s)
{
CString q;
char *p = q.GetBuffer(MAX_PATH);
ExtractFilePath(p,s,TRUE);
q.ReleaseBuffer();
return q;
}
void SplitDirs(char *Path, char *Dirs[], int &DirCount)
{
int i = 0;
int j = 0;
while (Path[i]) {
if ((Path[i] == '\\') || (Path[i] == '/')) {
Path[i] = 0;
Dirs[j] = &Path[i+1];
j++;
}
i++;
}
DirCount = j-1;
}
/*
* ExtractRelativePath()
* given BaseName and DestName, return relative path
* if BaseName empty, then relative path is compared against
* current directory
*
*/
CString ExtractRelativePath(const CString &BaseName,
const CString &DestName)
{
char BasePath[MAX_PATH];
char DestPath[MAX_PATH];
strcpy(BasePath,BaseName);
if (BaseName.IsEmpty()) {
GetCurrentDirectory(sizeof(BasePath),BasePath);
}
if (_stricmp(ExtractFileDrive(BasePath),
ExtractFileDrive(DestName))) {
return DestName;
}
strcpy(BasePath,ExtractFilePathNoDrive(BasePath));
strcpy(DestPath,ExtractFilePathNoDrive(DestName));
char *BaseDirs[130];
char *DestDirs[130];
int BaseDirCount = 0;
int DestDirCount = 0;
SplitDirs(BasePath, BaseDirs, BaseDirCount);
SplitDirs(DestPath, DestDirs, DestDirCount);
int i = 0;
while ((i < BaseDirCount) && (i < DestDirCount)) {
if (_stricmp(BaseDirs[i], DestDirs[i]) != 0) break;
i++;
}
CString Result = ".\\";
for (int j = i; j < BaseDirCount; j++)
Result += "..\\"; // Do not localize
for (int k = i; k < DestDirCount; k++) {
Result += CString(DestDirs[k]) + "\\"; // Do not localize
}
Result += ExtractFileName(DestName);
return Result;
}
//--------------------------------------------
// MAIN
//---------------------------------------------
void main(char argc, char *argv[])
{
CString base = ""; // assume current directory
CString dest = "v:\\local\\wc5\\common";
// expecting ".\\common"
printf("rel path: %s\n",ExtractRelativePath(base,dest));