// Gets the relative path of strPath (FILE) to strReference (DIRECTORY).
//
// Both filenames must be absolute names or I guarantee for nothing!
// Moreover, strReference must either be a FILE name or end with '\\'.
//
// Dependencies: CString (more dependency functions are included below)
//
// Web: http://unclassified.software/source/getrelativepath
//
CString GetRelativePath(CString strPath, CString strReference)
{
	int iPart;
	int iRemain;
	CString strOut;

	for (iPart = 0; iPart < StringPartCount(strPath, '\\'); iPart++)
	{
		if (StringPart(strPath, '\\', iPart).
			CompareNoCase(StringPart(strReference, '\\', iPart)))
		{
			// both strings differ in part# iPart
			if (iPart == 0)
			{
				// other drive must be specified entirely
				return strPath;
			}
			else
			{
				// first difference anywhere in a subfolder

				// determine number of remaining directory layers to the reference
				iRemain = StringPartCount(strReference, '\\') - 1 - iPart;
				while (iRemain--)
					strOut += "..\\";

				// differing path
				strOut += strPath.Mid(StringPartBegin(strPath, '\\', iPart));

				return strOut;
			}
		}
	}

	// no difference
	return ShellSplitLast(strPath);
}

// Dependencies:

CString StringPart(CString str, char cDelimiter, int nIndex)
{
	if (str.Find(cDelimiter) == -1) return str;

	int iPos = 0;
	int iEnd;
	CString str2;

	while (nIndex--)
	{
		iPos = str.Find(cDelimiter, iPos) + 1;
		if (!iPos) return str2;
	}

	iEnd = str.Find(cDelimiter, iPos);
	if (iEnd == -1) iEnd = str.GetLength();

	str2 = str.Mid(iPos, iEnd - iPos);

	return str2;
}

int StringPartCount(CString str, char cDelimiter)
{
	if (str.IsEmpty()) return 0;
	return str.Remove(cDelimiter) + 1;
}

int StringPartBegin(CString str, char cDelimiter, int nIndex)
{
	if (str.Find(cDelimiter) == -1) return 0;
	if (str.IsEmpty()) return 0;
	if (nIndex == 0) return 0;

	int iPos = 0;
	while (nIndex--)
	{
		iPos = str.Find(cDelimiter, iPos) + 1;
		if (!iPos) return iPos;
	}

	return iPos;
}

CString ShellGetLast(CString strPath)
{
	int pos = strPath.ReverseFind('\\');
	return strPath.Mid(pos + 1, strPath.GetLength() - pos - 1);
}

CString ShellSplitLast(CString strPath)
{
	int pos = strPath.ReverseFind('\\');
	return strPath.Left(pos);
}
