|
// Copyright (C) 2011 Fog Creek Software
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
#include "TortoiseUtils.h"
#include <io.h>
#include <fcntl.h>
CString GetTHgProgRoot()
{
LPCTSTR lpszKeyName = "Software\\TortoiseHg";
HKEY hKey = HKEY_LOCAL_MACHINE;
TCHAR lpszValue[MAX_PATH] = "";
LONG lpcbLonger = MAX_PATH * sizeof(TCHAR);
if (::RegQueryValue(hKey, lpszKeyName, lpszValue, &lpcbLonger) != ERROR_SUCCESS)
{
return "";
}
return lpszValue;
}
// Start an external command
// Note: if the command is a batch file and the [full] path to the
// batch contains spaces, the path must be double-quoted.
// (see http://www.encocoservices.com/createprocess.html)
bool LaunchCommand(const CString& strCommand, const CString& strCwd)
{
ATLTRACE("LaunchCommand: %s\n", (LPCTSTR)strCommand);
ATLTRACE("LaunchCommand: in '%s'\n", (LPCTSTR)strCwd);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
STARTUPINFOA si;
memset(&si, 0, sizeof(STARTUPINFO));
BOOL bRes = ::CreateProcess(
NULL, // No module name, use command line
(LPTSTR)(LPCTSTR)strCommand,
NULL, // Process handle not inherited
NULL, // Thread handle not inherited
FALSE,
CREATE_NO_WINDOW,
NULL, // use parent's environment
strCwd,
&si,
&pi);
if (bRes == 0)
{
ATLTRACE("LaunchCommand: failed to launch\n");
return false;
}
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
return true;
}
CString DirName(const CString& strFileName)
{
if (strFileName.IsEmpty()) return strFileName;
int nPos = strFileName.ReverseFind('\\');
if (nPos == -1) return "";
CString strDirName = strFileName.Left(nPos);
if (!strDirName.IsEmpty() && strDirName[strDirName.GetLength()-1] == ':')
{
strDirName.AppendChar('\\');
}
return strDirName;
}
CString BaseName(const CString& strFileName)
{
if (strFileName.IsEmpty()) return strFileName;
int nPos = strFileName.ReverseFind('\\');
if (nPos == -1) return strFileName;
return strFileName.Mid(nPos+1);
}
// not reentrant
HICON GetTortoiseIcon(const CString& strIconName)
{
typedef CAtlMap<CString, HICON> CIconCache;
static CIconCache iconcache;
CString thgdir = GetTHgProgRoot();
if (thgdir.IsEmpty())
{
ATLTRACE("GetTortoiseIcon: THG root is empty\n");
return 0;
}
CString strIconPath = thgdir + "\\icons\\" + strIconName;
const CIconCache::CPair* p = iconcache.Lookup(strIconName);
if (p != NULL) return p->m_value;
if (iconcache.GetCount() > 200)
{
ATLTRACE("**** GetTortoiseIcon: error: too many icons in cache\n");
return 0;
}
HICON hIcon = (HICON)::LoadImage(0, strIconPath, IMAGE_ICON,
16, 16, LR_LOADFROMFILE);
if (!hIcon)
{
ATLTRACE("GetTortoiseIcon: can't find '%s'\n", (LPCTSTR)strIconPath);
return 0;
}
iconcache[strIconPath] = hIcon;
ATLTRACE("GetTortoiseIcon: added '%s' to iconcache_ (%d icons in cache)\n",
(LPCTSTR)strIconPath, iconcache.GetCount());
return hIcon;
}
CString GetHgRepoRoot(LPCTSTR lpszPath)
{
ATLTRACE("GetHgRepoRoot('%s')\n", lpszPath);
CString strPath = (::PathIsUNCServerShare(lpszPath) || ::PathIsDirectory(lpszPath)) ?
lpszPath : DirName(lpszPath);
for (;;)
{
CString strHgDir = strPath + "\\.hg";
if (::PathIsUNCServerShare(strHgDir))
{
ATLTRACE("GetHgRepoRoot: tdir is UNC share '%s'\n", (LPCTSTR)strHgDir);
strPath.Empty();
break;
}
else if (::PathIsDirectory(strHgDir))
{
break;
}
CString strOldPath = strPath;
strPath = DirName(strPath);
if (strPath == strOldPath)
{
strPath.Empty();
break;
}
}
ATLTRACE("GetHgRepoRoot: returning '%s'\n", (LPCTSTR)strPath);
return strPath;
}
bool IsHgRepo(LPCTSTR lpszPath)
{
return !GetHgRepoRoot(lpszPath).IsEmpty();
}
// read string value from registry, wide version
bool GetRegSZValueW(HKEY hKey, LPCWSTR lpszName, CStringW& strRes)
{
strRes = L"";
if (!hKey) return 0;
DWORD cbData = 600;
LPWSTR lpszData = strRes.GetBuffer(cbData);
LONG lRes = ::RegQueryValueExW(hKey, lpszName, 0, 0, (LPBYTE)lpszData, &cbData);
strRes.ReleaseBuffer(cbData);
if (lRes == ERROR_SUCCESS) return true;
ATLTRACE(L"GetRegSZValueW('%s') failed\n", lpszName);
return false;
}
// true if a starts with b
bool StartsWith(const CString& strWhole, const CString& strPrefix)
{
if (strWhole.IsEmpty() || strPrefix.IsEmpty()) return false;
if (strPrefix.GetLength() > strWhole.GetLength()) return false;
for (int i = 0; i < strPrefix.GetLength(); ++i)
{
if (strWhole[i] != strPrefix[i]) return false;
}
return true;
}
void Tokenize(CString str, CAtlList<CString>& rTokens, LPCTSTR lpszDelimiters)
{
int nPos = 0;
CString strToken = str.Tokenize(lpszDelimiters, nPos);
while (!strToken.IsEmpty())
{
rTokens.AddTail(strToken);
strToken = str.Tokenize(lpszDelimiters, nPos);
}
}
|
Loading...