Beispiel #1
0
UpdaterState CUpdater::ProcessFinishedDownload()
{
	UpdaterState s = newversion;

	wxString const temp = GetTempFile();
	if( temp.empty() ) {
		s = newversion;
	}
	else if( !VerifyChecksum( temp, version_information_.available_.size_, version_information_.available_.hash_ ) ) {
		wxLogNull log;
		wxRemoveFile(temp);
		s = newversion;
	}
	else {
		s = newversion_ready;

		wxString local_file = GetLocalFile( version_information_.available_, false );

		wxLogNull log;
		if (local_file.empty() || !wxRenameFile( temp, local_file, false ) ) {
			s = newversion;
			wxRemoveFile( temp );
			log_ += wxString::Format(_("Could not create local file %s\n"), local_file.c_str());
		}
		else {
			local_file_ = local_file;
			log_ += wxString::Format(_("Local file is %s\n"), local_file.c_str());
		}
	}
	return s;
}
Beispiel #2
0
char* Copy2TmpFile(const wchar_t *fName, TFileType fType)
{
	char *tmpName, *tmpFileName=NULL;
	int numread = 0;

	tmpName = GetTempFile();
		
	if(tmpName == NULL)
		return NULL;

	tmpFileName = new char[strlen(tmpName)+5];
	strcpy(tmpFileName, tmpName);

	if(fType == CERTFILE)
		{
		tmpFileName = strcat(tmpFileName, ".cer");
		}	
	else if(fType == KEYFILE)
		{
		tmpFileName = strcat(tmpFileName, ".key");
		}
	else
		{
		tmpFileName = strcat(tmpFileName, ".dat");
		}

		TransferFileData(fName,tmpFileName);
		return tmpFileName;

		if(tmpFileName != NULL)
			delete tmpFileName;

	return NULL;
}
BOOL CCheckRuleXMLParse::Load(CheckRuleArray &arrCheckRuleList)
{
	BOOL bRet = FALSE;
	// 检查旧版本生成的未加密xml文件是否存在
	CString strOldXmlPath = m_strRuleFilePath;
	strOldXmlPath.Replace(L".bpxml", L"xml");
	if (IsFileExist(strOldXmlPath))
	{
		// 读取老版本生成的未加密xml
		if (CheckVersion(m_strRuleFilePath).CompareNoCase(L"1.0") == 0)
			bRet = Load(m_strRuleFilePath, arrCheckRuleList);
		if (CheckVersion(m_strRuleFilePath).CompareNoCase(L"1.1") == 0)
			bRet = LoadNew(m_strRuleFilePath, arrCheckRuleList);
	}
	else
	{
		if (IsFileExist(m_strRuleFilePath))
		{
			// 先解密再读取
			CString strTempXmlFile;
			GetTempFile(strTempXmlFile, L"xml");
			DecodeFileEx(m_strRuleFilePath, strTempXmlFile);
			if (CheckVersion(strTempXmlFile).CompareNoCase(L"1.0") == 0)
				bRet = Load(strTempXmlFile, arrCheckRuleList);
			if (CheckVersion(strTempXmlFile).CompareNoCase(L"1.1") == 0)
				bRet = LoadNew(strTempXmlFile, arrCheckRuleList);

			// 结束后删除临时xml文件
			SafeDeleteFile(strTempXmlFile);
		}
	}

	return bRet;
}
Beispiel #4
0
int CPatchListCtrl::LaunchProc(const CString& command)
{
	CString tempfile=GetTempFile();
	POSITION pos=this->GetFirstSelectedItemPosition();
	CFile file;
	file.Open(tempfile,CFile::modeWrite|CFile::modeCreate);

	while(pos)
	{
		int index = this->GetNextSelectedItem(pos);
		CString one=this->GetItemText(index,0);
		file.Write((LPCTSTR)one, sizeof(TCHAR) * one.GetLength());
		file.Write(_T("\n"),sizeof(TCHAR)*1);
	}

	file.Close();

	CString cmd = _T("/command:");
	cmd += command;
	cmd +=_T(" /pathfile:\"");
	cmd += tempfile;
	cmd += _T("\" /deletepathfile");
	CAppUtils::RunTortoiseGitProc(cmd);
	return 0;
}
bool ShowCompareCommand::Execute()
{
	CString		rev1;
	CString		rev2;

	bool		unified = !!parser.HasKey(_T("unified"));

	if (parser.HasVal(_T("revision1")))
		rev1 = parser.GetVal(_T("revision1"));
	if (parser.HasVal(_T("revision2")))
		rev2 = parser.GetVal(_T("revision2"));

	if (unified)
	{
		CString tempfile = GetTempFile();
		CString cmd;

		if (rev1.IsEmpty())
			cmd.Format(_T("git.exe diff -r -p --stat %s"), rev2);
		else if (rev2.IsEmpty())
			cmd.Format(_T("git.exe diff -r -p --stat %s"), rev1);
		else
			cmd.Format(_T("git.exe diff-tree -r -p --stat %s %s"), rev1, rev2);

		g_Git.RunLogFile(cmd, tempfile);
		return !!CAppUtils::StartUnifiedDiffViewer(tempfile, rev1 + _T(":") + rev2);
	}
	else
		return !!CGitDiff::DiffCommit(cmdLinePath, rev2, rev1);
}
Beispiel #6
0
UpdaterState CUpdater::ProcessFinishedData(bool can_download)
{
	UpdaterState s = failed;

	ParseData();

	if( version_information_.available_.version_.empty() ) {
		s = idle;
	}
	else if( !version_information_.available_.url_.empty() ) {

		wxString const temp = GetTempFile();
		wxString const local_file = GetLocalFile(version_information_.available_, true);
		if( !local_file.empty() && CLocalFileSystem::GetFileType(local_file) != CLocalFileSystem::unknown) {
			local_file_ = local_file;
			log_ += wxString::Format(_("Local file is %s\n"), local_file.c_str());
			s = newversion_ready;
		}
		else {
			// We got a checksum over a secure channel already.
			update_options_->m_use_internal_rootcert = false;

			if( temp.empty() || local_file.empty() ) {
				s = newversion;
			}
			else {
				s = newversion_downloading;
				wxLongLong size = CLocalFileSystem::GetSize(temp);
				if( size >= 0 && static_cast<unsigned long long>(size.GetValue()) >= version_information_.available_.size_ ) {
					s = ProcessFinishedDownload();
				}
				else if( !can_download || Download( version_information_.available_.url_, GetTempFile() ) != FZ_REPLY_WOULDBLOCK ) {
					s = newversion;
				}
			}
		}
	}
	else {
		s = newversion;
	}

	return s;
}
void CSettingGitConfig::OnBnClickedEdittgitconfig()
{
	// use alternative editor because of LineEndings
	if (GitAdminDir::IsBareRepo(g_Git.m_CurrentDir))
	{
		CString tmpFile = GetTempFile();
		CTGitPath path(_T(".tgitconfig"));
		if (g_Git.GetOneFile(_T("HEAD"), path, tmpFile) == 0)
		{
			CAppUtils::LaunchAlternativeEditor(tmpFile);
		}
	}
	else
	{
		CAppUtils::LaunchAlternativeEditor(g_Git.m_CurrentDir + _T("\\.tgitconfig"));
	}
}
Beispiel #8
0
BOOL CGravador::RodaOsql(CString strScript, DWORD * pdwExitCode, CString strRun)
{
	// cria o arquivo de script em um diretório temporário
	CString strTempFile;
	strTempFile = GetTempFile(strScript);

	// monta a linha de comando incluíndo usuário e senha se for o caso
	CString strCmdLine;
	strCmdLine = MontaLinhaComando(strTempFile, strRun);

	BOOL bResult;
	bResult = RodaConsole(pdwExitCode, strCmdLine);

	// apaga arquivo temporário
	DeleteFile(strTempFile);

	return bResult;
}
void CSettingGitConfig::OnBnClickedEdittgitconfig()
{
	// use alternative editor because of LineEndings
	if (GitAdminDir::IsBareRepo(g_Git.m_CurrentDir))
	{
		CString tmpFile = GetTempFile();
		CTGitPath path(L".tgitconfig");
		if (g_Git.GetOneFile(L"HEAD", path, tmpFile) == 0)
		{
			::SetFileAttributes(tmpFile, FILE_ATTRIBUTE_READONLY);
			CAppUtils::LaunchAlternativeEditor(tmpFile);
		}
	}
	else
	{
		CAppUtils::LaunchAlternativeEditor(g_Git.m_CurrentDir + L"\\.tgitconfig");
	}
}
Beispiel #10
0
wxULongLong CUpdater::BytesDownloaded() const
{
	wxLongLong ret;
	if( state_ == newversion_ready ) {
		if( !local_file_.empty() ) {
			ret = CLocalFileSystem::GetSize(local_file_);
		}
	}
	else if( state_ == newversion_downloading ) {
		wxString const temp = GetTempFile();
		if( !temp.empty() ) {
			ret = CLocalFileSystem::GetSize(temp);
		}
	}
	if( ret < 0 ) {
		ret = 0;
	}
	return static_cast<unsigned long long>(ret.GetValue());
}
BOOL CCheckRuleXMLParse::Save(const CString &strFilePath, const CheckRuleArray &arrCheckRuleList)
{
	// 删除老版本生成的未加密xml
	CString strOldXmlPath = strFilePath;
	strOldXmlPath.Replace(L".bpxml", L"xml");
	if (IsFileExist(strOldXmlPath))
		SafeDeleteFile(strOldXmlPath);

	// 删除新版本生成的加密bpxml
	if (IsFileExist(strFilePath))
		SafeDeleteFile(strFilePath);

	BOOL bResult = TRUE;

	// 初始化
	Init();

	// 创建xml文件
	if (!m_pXMLDocument->CreateDocument(L"CheckRule"))
		bResult = FALSE;

	// 存储数据
	if (bResult)
	{
		IBpXMLNode* pRootNode = m_pXMLDocument->GetRootElement();
		pRootNode->SetAttribute(L"version", L"1.1");
		DestroyXMLNode(pRootNode);
		CString strValue;	
		for (int i=0; i<arrCheckRuleList.GetSize(); i++)
		{
			IBpXMLNode* pRuleNode = m_pXMLDocument->CreateElementNode(L"node");
			IBpXMLNode* pChildNode = NULL;
			if (pRuleNode != NULL)
			{
				strValue.Format(L"%d", arrCheckRuleList[i].nID);
				pRuleNode->SetAttribute(L"id", strValue);
				strValue.Format(L"%d", arrCheckRuleList[i].nRuleType);
				pRuleNode->SetAttribute(L"ruletype", strValue);
				pChildNode = pRuleNode->AppendNewElementChild(L"ruledesc");
				pChildNode->SetText(arrCheckRuleList[i].strRuleDesc);
				DestroyXMLNode(pChildNode);
				pChildNode = pRuleNode->AppendNewElementChild(L"rulename");
				pChildNode->SetText(arrCheckRuleList[i].strRuleName);
				DestroyXMLNode(pChildNode);
				pChildNode = pRuleNode->AppendNewElementChild(L"rulecontent");

				for (int j=0; j<arrCheckRuleList[i].arrRuleContent.GetCount(); j++)
				{
					strValue.Format(L"rc%d", j);
					pChildNode->SetAttribute(strValue, arrCheckRuleList[i].arrRuleContent.GetAt(j));
				}
				DestroyXMLNode(pChildNode);
				pChildNode = pRuleNode->AppendNewElementChild(L"MdlFilter");
				strValue.Format(L"%d", arrCheckRuleList[i].dwMdlFilter);
				pChildNode->SetText(strValue);
				DestroyXMLNode(pChildNode);

				DestroyXMLNode(pRuleNode);
			}
		}
	}

	// 保存为临时xml文件
	CString strTempXMLFile;
	GetTempFile(strTempXMLFile, L"xml");
	m_pXMLDocument->SaveXML(strTempXMLFile);

	// xml文件加密
	bResult = EncodeFileEx(strTempXMLFile, strFilePath);
	SafeDeleteFile(strTempXMLFile);

	// 释放资源
	Uninit();
	return bResult;
}
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev)
{
	if(Rev.IsEmpty())
		Rev = _T("HEAD");

	// enable blame for files which do not exist in current working tree
	if (!PathFileExists(lpszPathName) && Rev != _T("HEAD"))
	{
		if (!CDocument::OnOpenDocument(GetTempFile()))
			return FALSE;
	}
	else
	{
		if (!CDocument::OnOpenDocument(lpszPathName))
			return FALSE;
	}

	m_CurrentFileName = lpszPathName;

	m_Rev=Rev;

	// (SDI documents will reuse this document)
	if(!g_Git.CheckMsysGitDir())
	{
		CCommonAppUtils::RunTortoiseGitProc(_T(" /command:settings"));
		return FALSE;
	}
	CString topdir;
	if (!GitAdminDir::HasAdminDir(m_CurrentFileName, &topdir))
	{
		CString temp;
		temp.Format(IDS_CANNOTBLAMENOGIT, (LPCTSTR)m_CurrentFileName);
		MessageBox(nullptr, temp, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);
		return FALSE;
	}
	else
	{
		m_IsGitFile=TRUE;
		sOrigCWD = g_Git.m_CurrentDir = topdir;

		CString PathName = m_CurrentFileName;
		if(topdir[topdir.GetLength()-1] == _T('\\') ||
			topdir[topdir.GetLength()-1] == _T('/'))
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength());
		else
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1);

		CTGitPath path;
		path.SetFromWin(PathName);

		if(!g_Git.m_CurrentDir.IsEmpty())
			SetCurrentDirectory(g_Git.m_CurrentDir);

		try
		{
			// make sure all config files are read in order to check that none contains an error
			g_Git.GetConfigValue(_T("doesnot.exist"));
		}
		catch (char * libgiterr)
		{
			MessageBox(nullptr, CString(libgiterr), _T("TortoiseGitBlame"), MB_ICONERROR);
			return FALSE;
		}

		CString cmd, option;
		int dwDetectMovedOrCopiedLines = theApp.GetInt(_T("DetectMovedOrCopiedLines"), BLAME_DETECT_MOVED_OR_COPIED_LINES_DISABLED);
		int dwDetectMovedOrCopiedLinesNumCharactersWithinFile = theApp.GetInt(_T("DetectMovedOrCopiedLinesNumCharactersWithinFile"), BLAME_DETECT_MOVED_OR_COPIED_LINES_NUM_CHARACTERS_WITHIN_FILE_DEFAULT);
		int dwDetectMovedOrCopiedLinesNumCharactersFromFiles = theApp.GetInt(_T("DetectMovedOrCopiedLinesNumCharactersFromFiles"), BLAME_DETECT_MOVED_OR_COPIED_LINES_NUM_CHARACTERS_FROM_FILES_DEFAULT);
		switch(dwDetectMovedOrCopiedLines)
		{
		default:
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_DISABLED:
			option.Empty();
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_WITHIN_FILE:
			option.Format(_T("-M%d"), dwDetectMovedOrCopiedLinesNumCharactersWithinFile);
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_MODIFIED_FILES:
			option.Format(_T("-C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles);
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_EXISTING_FILES_AT_FILE_CREATION:
			option.Format(_T("-C -C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles);
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_EXISTING_FILES:
			option.Format(_T("-C -C -C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles);
			break;
		}

		if (theApp.GetInt(_T("IgnoreWhitespace"), 0) == 1)
			option += _T(" -w");

		cmd.Format(_T("git.exe blame -p %s %s -- \"%s\""), (LPCTSTR)option, (LPCTSTR)Rev, (LPCTSTR)path.GetGitPathString());
		m_BlameData.clear();
		BYTE_VECTOR err;
		if(g_Git.Run(cmd, &m_BlameData, &err))
		{
			CString str;
			if (!m_BlameData.empty())
				CGit::StringAppend(&str, &m_BlameData[0], CP_UTF8);
			if (!err.empty())
				CGit::StringAppend(&str, &err[0], CP_UTF8);
			MessageBox(nullptr, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);

			return FALSE;
		}

#ifdef USE_TEMPFILENAME
		if(!m_TempFileName.IsEmpty())
		{
			::DeleteFile(m_TempFileName);
			m_TempFileName.Empty();
		}

		m_TempFileName=GetTempFile();

		cmd.Format(_T("git.exe cat-file blob %s:\"%s\""), (LPCTSTR)Rev, (LPCTSTR)path.GetGitPathString());

		if(g_Git.RunLogFile(cmd, m_TempFileName))
		{
			CString str;
			str.Format(IDS_CHECKOUTFAILED, (LPCTSTR)path.GetGitPathString());
			MessageBox(nullptr, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);
			return FALSE;
		}
#endif
		m_GitPath = path;

		CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView());
		if (!pView)
		{
			CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
			if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView)))
			{
				pView = (CTortoiseGitBlameView*)pWnd;
			}
			else
			{
				return FALSE;
			}
		}
		pView->ParseBlame();

		BOOL bShowCompleteLog = (theApp.GetInt(_T("ShowCompleteLog"), 1) == 1);
		if (bShowCompleteLog && BlameIsLimitedToOneFilename(dwDetectMovedOrCopiedLines))
		{
			if (GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString(), m_Rev, (theApp.GetInt(_T("FollowRenames"), 0) == 1)))
				return FALSE;
		}
		else
		{
			std::set<CGitHash> hashes;
			pView->m_data.GetHashes(hashes);
			if (GetMainFrame()->m_wndOutput.LoadHistory(hashes))
				return FALSE;
		}

		pView->MapLineToLogIndex();
		pView->UpdateInfo();
		if (m_lLine > 0)
			pView->GotoLine(m_lLine);

		SetPathName(m_CurrentFileName, FALSE);
	}

	return TRUE;
}
int ProjectProperties::ReadProps(CTGitPath path)
{
	if (gitconfig)
		git_config_free(gitconfig);

	git_config_new(&gitconfig);
	CString adminDirPath;
	if (g_GitAdminDir.GetAdminDirPath(g_Git.m_CurrentDir, adminDirPath))
	{
		CStringA configFile = CUnicodeUtils::GetUTF8(adminDirPath) + "config";
		git_config_add_file_ondisk(gitconfig, configFile, 5, FALSE);
	}

	if (!g_GitAdminDir.IsBareRepo(g_Git.m_CurrentDir))
	{
		CStringA configFile = CUnicodeUtils::GetUTF8(g_Git.m_CurrentDir) + "\\.tgitconfig";
		git_config_add_file_ondisk(gitconfig, configFile, 4, FALSE);
	}
	else
	{
		CString tmpFile = GetTempFile();
		CTGitPath path(_T(".tgitconfig"));
		if (g_Git.GetOneFile(_T("HEAD"), path, tmpFile) == 0)
		{
			CStringA configFile = CUnicodeUtils::GetUTF8(tmpFile);
			git_config_add_file_ondisk(gitconfig, configFile, 4, FALSE);
		}
	}

	CStringA globalConfigA = CUnicodeUtils::GetUTF8(g_Git.GetGitGlobalConfig());
	git_config_add_file_ondisk(gitconfig, globalConfigA.GetBuffer(), 3, FALSE);
	globalConfigA.ReleaseBuffer();
	CStringA globalXDGConfigA = CUnicodeUtils::GetUTF8( g_Git.GetGitGlobalXDGConfig());
	git_config_add_file_ondisk(gitconfig, globalXDGConfigA.GetBuffer(), 2, FALSE);
	globalXDGConfigA.ReleaseBuffer();
	CStringA systemConfigA = CUnicodeUtils::GetUTF8(g_Git.ms_LastMsysGitDir + _T("\\..\\etc\\gitconfig"));
	git_config_add_file_ondisk(gitconfig, systemConfigA.GetBuffer(), 1, FALSE);
	systemConfigA.ReleaseBuffer();
	giterr_clear();

	CString sPropVal;

	GetStringProps(this->sLabel,BUGTRAQPROPNAME_LABEL);
	GetStringProps(this->sMessage,BUGTRAQPROPNAME_MESSAGE);
	nBugIdPos = sMessage.Find(L"%BUGID%");
	GetStringProps(this->sUrl,BUGTRAQPROPNAME_URL);

	GetBOOLProps(this->bWarnIfNoIssue,BUGTRAQPROPNAME_WARNIFNOISSUE);
	GetBOOLProps(this->bNumber,BUGTRAQPROPNAME_NUMBER);
	GetBOOLProps(this->bAppend,BUGTRAQPROPNAME_APPEND);

	GetStringProps(sProviderUuid, BUGTRAQPROPNAME_PROVIDERUUID);
	GetStringProps(sProviderUuid64, BUGTRAQPROPNAME_PROVIDERUUID64);
	GetStringProps(sProviderParams, BUGTRAQPROPNAME_PROVIDERPARAMS);

	GetBOOLProps(this->bWarnNoSignedOffBy, PROJECTPROPNAME_WARNNOSIGNEDOFFBY);

	GetStringProps(sPropVal, BUGTRAQPROPNAME_LOGREGEX);

	sCheckRe = sPropVal;
	if (sCheckRe.Find('\n')>=0)
	{
		sBugIDRe = sCheckRe.Mid(sCheckRe.Find('\n')).Trim();
		sCheckRe = sCheckRe.Left(sCheckRe.Find('\n')).Trim();
	}
	if (!sCheckRe.IsEmpty())
	{
		sCheckRe = sCheckRe.Trim();
	}

	if (GetStringProps(sPropVal, PROJECTPROPNAME_LOGWIDTHLINE) == 0)
	{
		CString val;
		val = sPropVal;
		if (!val.IsEmpty())
			nLogWidthMarker = _ttoi(val) + 2; // HACK, + 2 needed
	}

	if (GetStringProps(sPropVal, PROJECTPROPNAME_PROJECTLANGUAGE) == 0)
	{
		CString val;
		val = sPropVal;
		if (!val.IsEmpty())
		{
			LPTSTR strEnd;
			lProjectLanguage = _tcstol(val, &strEnd, 0);
		}
	}

	if (GetStringProps(sPropVal, PROJECTPROPNAME_LOGMINSIZE) == 0)
	{
		CString val;
		val = sPropVal;
		if (!val.IsEmpty())
			nMinLogSize = _ttoi(val);
	}

	return 0;
}
Beispiel #14
0
void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect, CMenu *popmenu)
{
	POSITION pos = GetFirstSelectedItemPosition();
	int indexNext = GetNextSelectedItem(pos);
	if (indexNext < 0)
		return;

	GitRev* pSelLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(indexNext));

	theApp.DoWaitCursor(1);
	switch (cmd&0xFFFF)
		{
			case ID_COMMIT:
			{
				CTGitPathList pathlist;
				CTGitPathList selectedlist;
				pathlist.AddPath(this->m_Path);
				bool bSelectFilesForCommit = !!DWORD(CRegStdDWORD(_T("Software\\TortoiseGit\\SelectFilesForCommit"), TRUE));
				CString str;
				CAppUtils::Commit(CString(),false,str,
								  pathlist,selectedlist,bSelectFilesForCommit);
				//this->Refresh();
				this->GetParent()->PostMessage(WM_COMMAND,ID_LOGDLG_REFRESH,0);
			}
			break;
			case ID_GNUDIFF1:
			{
				CString tempfile=GetTempFile();
				CString command;
				GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
				if(!r1->m_CommitHash.IsEmpty())
				{
					CString merge;
					CString hash2;
					cmd >>= 16;
					if( (cmd&0xFFFF) == 0xFFFF)
					{
						merge=_T("-m");
					}
					else if((cmd&0xFFFF) == 0xFFFE)
					{
						merge=_T("-c");
					}
					else
					{
						if(cmd > r1->m_ParentHash.size())
						{
							CString str;
							str.Format(_T("Parent %d does not exist"), cmd);
							CMessageBox::Show(NULL,str,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
							return;
						}
						else
						{
							if(cmd>0)
								hash2 = r1->m_ParentHash[cmd-1].ToString();
						}
					}
					command.Format(_T("git.exe diff-tree %s -r -p --stat %s %s"), merge, hash2, r1->m_CommitHash.ToString());
				}
				else
					command.Format(_T("git.exe diff -r -p --stat"));

				g_Git.RunLogFile(command,tempfile);
				CAppUtils::StartUnifiedDiffViewer(tempfile,r1->m_CommitHash.ToString().Left(6)+_T(":")+r1->GetSubject());
			}
void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect, CMenu *popmenu)
{
	POSITION pos = GetFirstSelectedItemPosition();
	int indexNext = GetNextSelectedItem(pos);
	if (indexNext < 0)
		return;

	GitRevLoglist* pSelLogEntry = reinterpret_cast<GitRevLoglist*>(m_arShownList.GetAt(indexNext));

	theApp.DoWaitCursor(1);
	switch (cmd&0xFFFF)
		{
			case ID_COMMIT:
			{
				CTGitPathList pathlist;
				CTGitPathList selectedlist;
				pathlist.AddPath(this->m_Path);
				bool bSelectFilesForCommit = !!DWORD(CRegStdDWORD(_T("Software\\TortoiseGit\\SelectFilesForCommit"), TRUE));
				CString str;
				CAppUtils::Commit(CString(),false,str,
								  pathlist,selectedlist,bSelectFilesForCommit);
				//this->Refresh();
				this->GetParent()->PostMessage(WM_COMMAND,ID_LOGDLG_REFRESH,0);
			}
			break;
			case ID_MERGE_ABORT:
			{
				if (CAppUtils::MergeAbort())
					this->GetParent()->PostMessage(WM_COMMAND,ID_LOGDLG_REFRESH, 0);
			}
			break;
			case ID_GNUDIFF1: // compare with WC, unified
			{
				GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
				bool bMerge = false, bCombine = false;
				CString hash2;
				if(!r1->m_CommitHash.IsEmpty())
				{
					CString merge;
					cmd >>= 16;
					if( (cmd&0xFFFF) == 0xFFFF)
						bMerge = true;
					else if((cmd&0xFFFF) == 0xFFFE)
						bCombine = true;
					else if ((cmd & 0xFFFF) == 0xFFFD)
					{
						CString tempfile = GetTempFile();
						CString gitcmd = _T("git.exe diff-tree --cc ") + r1->m_CommitHash.ToString();
						CString lastErr;
						if (g_Git.RunLogFile(gitcmd, tempfile, &lastErr))
						{
							MessageBox(lastErr, _T("TortoiseGit"), MB_ICONERROR);
							break;
						}

						try
						{
							CStdioFile file(tempfile, CFile::typeText | CFile::modeRead | CFile::shareDenyWrite);
							CString strLine;
							bool isHash = file.ReadString(strLine) && r1->m_CommitHash.ToString() == strLine;
							bool more = isHash && file.ReadString(strLine) && !strLine.IsEmpty();
							if (!more)
							{
								CMessageBox::Show(nullptr, IDS_NOCHANGEAFTERMERGE, IDS_APPNAME, MB_OK);
								break;
							}
						}
						catch (CFileException* e)
						{
							e->Delete();
						}

						CAppUtils::StartUnifiedDiffViewer(tempfile, _T("dd"));
						break;
					}
					else
					{
						if ((size_t)cmd > r1->m_ParentHash.size())
						{
							CString str;
							str.Format(IDS_PROC_NOPARENT, cmd);
							MessageBox(str, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
							return;
						}
						else
						{
							if(cmd>0)
								hash2 = r1->m_ParentHash[cmd-1].ToString();
						}
					}
					CAppUtils::StartShowUnifiedDiff(nullptr, CTGitPath(), hash2, CTGitPath(), r1->m_CommitHash.ToString(), false, false, false, bMerge, bCombine);
				}
				else
					CAppUtils::StartShowUnifiedDiff(nullptr, CTGitPath(), _T("HEAD"), CTGitPath(), GitRev::GetWorkingCopy(), false, false, false, bMerge, bCombine);
			}
int ProjectProperties::ReadProps()
{
	CAutoConfig gitconfig(true);
	CString adminDirPath;
	if (g_GitAdminDir.GetAdminDirPath(g_Git.m_CurrentDir, adminDirPath))
		git_config_add_file_ondisk(gitconfig, CGit::GetGitPathStringA(adminDirPath + L"config"), GIT_CONFIG_LEVEL_APP, FALSE); // this needs to have the highest priority in order to override .tgitconfig settings

	if (!g_GitAdminDir.IsBareRepo(g_Git.m_CurrentDir))
		git_config_add_file_ondisk(gitconfig, CGit::GetGitPathStringA(g_Git.CombinePath(L".tgitconfig")), GIT_CONFIG_LEVEL_LOCAL, FALSE); // this needs to have the second highest priority
	else
	{
		CString tmpFile = GetTempFile();
		CTGitPath path(_T(".tgitconfig"));
		if (g_Git.GetOneFile(_T("HEAD"), path, tmpFile) == 0)
			git_config_add_file_ondisk(gitconfig, CGit::GetGitPathStringA(tmpFile), GIT_CONFIG_LEVEL_LOCAL, FALSE); // this needs to have the second highest priority
	}

	git_config_add_file_ondisk(gitconfig, CGit::GetGitPathStringA(g_Git.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
	git_config_add_file_ondisk(gitconfig,CGit::GetGitPathStringA(g_Git.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG, FALSE);
	git_config_add_file_ondisk(gitconfig, CGit::GetGitPathStringA(g_Git.ms_LastMsysGitDir + _T("\\..\\etc\\gitconfig")), GIT_CONFIG_LEVEL_SYSTEM, FALSE);
	giterr_clear();

	CString sPropVal;

	gitconfig.GetString(BUGTRAQPROPNAME_LABEL, sLabel);
	gitconfig.GetString(BUGTRAQPROPNAME_MESSAGE, sMessage);
	nBugIdPos = sMessage.Find(L"%BUGID%");
	gitconfig.GetString(BUGTRAQPROPNAME_URL, sUrl);

	gitconfig.GetBOOL(BUGTRAQPROPNAME_WARNIFNOISSUE, bWarnIfNoIssue);
	gitconfig.GetBOOL(BUGTRAQPROPNAME_NUMBER, bNumber);
	gitconfig.GetBOOL(BUGTRAQPROPNAME_APPEND, bAppend);

	gitconfig.GetString(BUGTRAQPROPNAME_PROVIDERUUID, sProviderUuid);
	gitconfig.GetString(BUGTRAQPROPNAME_PROVIDERUUID64, sProviderUuid64);
	gitconfig.GetString(BUGTRAQPROPNAME_PROVIDERPARAMS, sProviderParams);

	gitconfig.GetBOOL(PROJECTPROPNAME_WARNNOSIGNEDOFFBY, bWarnNoSignedOffBy);
	gitconfig.GetString(PROJECTPROPNAME_ICON, sIcon);

	gitconfig.GetString(BUGTRAQPROPNAME_LOGREGEX, sPropVal);

	sCheckRe = sPropVal;
	if (sCheckRe.Find('\n')>=0)
	{
		sBugIDRe = sCheckRe.Mid(sCheckRe.Find('\n')).Trim();
		sCheckRe = sCheckRe.Left(sCheckRe.Find('\n')).Trim();
	}
	if (!sCheckRe.IsEmpty())
	{
		sCheckRe = sCheckRe.Trim();
	}

	if (gitconfig.GetString(PROJECTPROPNAME_LOGWIDTHLINE, sPropVal) == 0)
	{
		CString val;
		val = sPropVal;
		if (!val.IsEmpty())
			nLogWidthMarker = _ttoi(val) + 2; // HACK, + 2 needed
	}

	if (gitconfig.GetString(PROJECTPROPNAME_PROJECTLANGUAGE, sPropVal) == 0)
	{
		CString val;
		val = sPropVal;
		if (val == _T("-1"))
			lProjectLanguage = -1;
		if (!val.IsEmpty())
		{
			LPTSTR strEnd;
			lProjectLanguage = _tcstol(val, &strEnd, 0);
		}
	}

	if (gitconfig.GetString(PROJECTPROPNAME_LOGMINSIZE, sPropVal) == 0)
	{
		CString val;
		val = sPropVal;
		if (!val.IsEmpty())
			nMinLogSize = _ttoi(val);
	}

	return 0;
}
void CGitBlameLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect,CMenu * menu)
{
	POSITION pos = GetFirstSelectedItemPosition();
	int indexNext = GetNextSelectedItem(pos);
	if (indexNext < 0)
		return;

	CString  procCmd;

	GitRev* pSelLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(indexNext));

	bool bOpenWith = false;

	procCmd += _T("/path:\"");
	procCmd += ((CMainFrame*)::AfxGetApp()->GetMainWnd())->GetActiveView()->GetDocument()->GetPathName();
	procCmd += _T("\" ");
	procCmd += _T(" /rev:")+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();

	procCmd += _T(" /command:");

	switch (cmd)
	{
		case ID_GNUDIFF1:
			procCmd += _T("diff /udiff");
		break;

#if 0
		case ID_GNUDIFF2:
			{
				CString tempfile=GetTempFile();
				CString cmd;
				GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
				GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));
				cmd.Format(_T("git.exe diff-tree -r -p --stat %s %s"),r1->m_CommitHash,r2->m_CommitHash);
				g_Git.RunLogFile(cmd,tempfile);
				CAppUtils::StartUnifiedDiffViewer(tempfile, r1->m_CommitHash.Left(g_Git.GetShortHASHLength()) + _T(":") + r2->m_CommitHash.Left(g_Git.GetShortHASHLength()));

			}
			break;
#endif
#if 0
		case ID_COMPARETWO:
			{
				GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
				GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));
				CFileDiffDlg dlg;
				dlg.SetDiff(NULL,*r1,*r2);
				dlg.DoModal();

			}
			break;
#endif
#if 0
		case ID_COMPARE:
			{
				GitRev * r1 = &m_wcRev;
				GitRev * r2 = pSelLogEntry;
				CFileDiffDlg dlg;
				dlg.SetDiff(NULL,*r1,*r2);
				dlg.DoModal();

				//user clicked on the menu item "compare with working copy"
				//if (PromptShown())
				//{
				//	GitDiff diff(this, m_hWnd, true);
				//	diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
				//	diff.SetHEADPeg(m_LogRevision);
				//	diff.ShowCompare(m_path, GitRev::REV_WC, m_path, revSelected);
				//}
				//else
				//	CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_WC, m_path, revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
			}
			break;
		case ID_COMPARE:
			procCmd+=CString(_T("diff \rev1:"))+CString(GIT_REV_ZERO)+CString(_T(" \rev2:"))+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
			break;
#endif
		case ID_COMPAREWITHPREVIOUS:
			if (indexNext + 1 < m_logEntries.size()) // cannot diff previous revision in first revision
			{
				procCmd+=CString(_T("diff /startrev:"))+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString()+CString(_T(" /endrev:"))+this->m_logEntries.GetGitRevAt(indexNext+1).m_CommitHash.ToString();
			}
			else
			{
				return;
			}
			break;
		case ID_COPYCLIPBOARD:
			{
				CopySelectionToClipBoard();
			}
			return;
		case ID_COPYHASH:
			{
				CopySelectionToClipBoard(TRUE);
			}
			return;
		case ID_EXPORT:
			procCmd += _T("export");
			break;
		case ID_CREATE_BRANCH:
			procCmd += _T("branch");
			break;
		case ID_CREATE_TAG:
			procCmd += _T("tag");
			break;
		case ID_SWITCHTOREV:
			procCmd += _T("switch");
			break;
		case ID_BLAME:
			procCmd += _T("blame");
			procCmd += _T(" /endrev:") + this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
			break;
		case ID_LOG:
			procCmd += _T("log");
			break;
		case ID_REPOBROWSE:
			procCmd.Format(_T("/command:repobrowser /path:\"%s\" /rev:%s"), g_Git.m_CurrentDir, this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString());
			break;
		default:
			//CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);
			return;

#if 0

		case ID_REVERTREV:
			{
				// we need an URL to complete this command, so error out if we can't get an URL
				if (pathURL.IsEmpty())
				{
					CString strMessage;
					strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
					CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
					TRACE(_T("could not retrieve the URL of the folder!\n"));
					break;		//exit
				}
				CString msg;
				msg.Format(IDS_LOG_REVERT_CONFIRM, m_path.GetWinPath());
				if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
				{
					CGitProgressDlg dlg;
					dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
					dlg.SetPathList(CTGitPathList(m_path));
					dlg.SetUrl(pathURL);
					dlg.SetSecondUrl(pathURL);
					revisionRanges.AdjustForMerge(true);
					dlg.SetRevisionRanges(revisionRanges);
					dlg.SetPegRevision(m_LogRevision);
					dlg.DoModal();
				}
			}
			break;
		case ID_FINDENTRY:
			{
				m_nSearchIndex = GetSelectionMark();
				if (m_nSearchIndex < 0)
					m_nSearchIndex = 0;
				if (m_pFindDialog)
				{
					break;
				}
				else
				{
					m_pFindDialog = new CFindReplaceDialog();
					m_pFindDialog->Create(TRUE, NULL, NULL, FR_HIDEUPDOWN | FR_HIDEWHOLEWORD, this);
				}
			}
			break;
#endif

		} // switch (cmd)

		CCommonAppUtils::RunTortoiseProc(procCmd);
}
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev)
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;

	m_CurrentFileName=lpszPathName;
	m_Rev=Rev;

	// (SDI documents will reuse this document)
	if(!g_Git.CheckMsysGitDir())
	{
		CMessageBox::Show(NULL,_T("MsysGit have not install or config fail"),_T("TortoiseGitBlame"),MB_OK);
		return FALSE;
	}

	GitAdminDir admindir;
	CString topdir;
	if(!admindir.HasAdminDir(lpszPathName,&topdir))
	{
		CMessageBox::Show(NULL,CString(lpszPathName)+_T(" is not controled by git\nJust Show File Context"),_T("TortoiseGitBlame"),MB_OK);
	}
	else
	{
		m_IsGitFile=TRUE;
		g_Git.m_CurrentDir=topdir;

		CString PathName=lpszPathName;
		if(topdir[topdir.GetLength()-1] == _T('\\') ||
			topdir[topdir.GetLength()-1] == _T('/'))
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength());
		else
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1);

		CTGitPath path;
		path.SetFromWin(PathName);

		if(!g_Git.m_CurrentDir.IsEmpty())
			SetCurrentDirectory(g_Git.m_CurrentDir);

		m_GitPath = path;
		GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString());

		CString cmd;

		if(Rev.IsEmpty())
			Rev=_T("HEAD");

		cmd.Format(_T("git.exe blame -s -l %s -- \"%s\""),Rev,path.GetGitPathString());
		m_BlameData.clear();
		BYTE_VECTOR err;
		if(g_Git.Run(cmd, &m_BlameData, &err))
		{
			CString str;
			g_Git.StringAppend(&str, &m_BlameData[0], CP_ACP);
			g_Git.StringAppend(&str, &err[0], CP_ACP);
			CMessageBox::Show(NULL,CString(_T("Blame Error")) + str,_T("TortoiseGitBlame"),MB_OK);

		}

		if(!m_TempFileName.IsEmpty())
		{
			::DeleteFile(m_TempFileName);
			m_TempFileName.Empty();
		}

		m_TempFileName=GetTempFile();

		if(Rev.IsEmpty())
			Rev=_T("HEAD");

		cmd.Format(_T("git.exe cat-file blob %s:\"%s\""),Rev,path.GetGitPathString());

		if(g_Git.RunLogFile(cmd, m_TempFileName))
		{
			CString str;
			str.Format(_T("Fail get file %s"), path.GetGitPathString());
			CMessageBox::Show(NULL,CString(_T("Blame Error")) + str,_T("TortoiseGitBlame"),MB_OK);
		}

		CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView());
		if(pView == NULL)
		{
			CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
			if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView)))
			{
				pView = (CTortoiseGitBlameView*)pWnd;
			}
			else
			{
				return FALSE;
			}
		}
		pView->UpdateInfo();
	}

	return TRUE;
}
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev)
{
	if(Rev.IsEmpty())
		Rev = _T("HEAD");

	// enable blame for files which do not exist in current working tree
	if (!PathFileExists(lpszPathName) && Rev != _T("HEAD"))
	{
		if (!CDocument::OnOpenDocument(GetTempFile()))
			return FALSE;
	}
	else
	{
		if (!CDocument::OnOpenDocument(lpszPathName))
			return FALSE;
	}

	m_CurrentFileName = lpszPathName;

	m_Rev=Rev;

	// (SDI documents will reuse this document)
	if(!g_Git.CheckMsysGitDir())
	{
		CCommonAppUtils::RunTortoiseGitProc(_T(" /command:settings"));
		return FALSE;
	}
	GitAdminDir admindir;
	CString topdir;
	if(!admindir.HasAdminDir(m_CurrentFileName, &topdir))
	{
		CString temp;
		temp.Format(IDS_CANNOTBLAMENOGIT, CString(m_CurrentFileName));
		CMessageBox::Show(NULL, temp, _T("TortoiseGitBlame"), MB_OK);
		return FALSE;
	}
	else
	{
		GitAdminDir lastAdminDir;
		CString oldTopDir;
		if (topdir != g_Git.m_CurrentDir && CTGitPath(g_Git.m_CurrentDir).HasAdminDir(&oldTopDir) && oldTopDir != topdir)
		{
			CString sMsg;
			sMsg.Format(IDS_ERR_DIFFENERTPREPO, oldTopDir, topdir);
			MessageBox(NULL, sMsg, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);
			return FALSE;
		}

		m_IsGitFile=TRUE;
		sOrigCWD = g_Git.m_CurrentDir = topdir;

		CString PathName = m_CurrentFileName;
		if(topdir[topdir.GetLength()-1] == _T('\\') ||
			topdir[topdir.GetLength()-1] == _T('/'))
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength());
		else
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1);

		CTGitPath path;
		path.SetFromWin(PathName);

		if(!g_Git.m_CurrentDir.IsEmpty())
			SetCurrentDirectory(g_Git.m_CurrentDir);

		try
		{
			// make sure all config files are read in order to check that none contains an error
			g_Git.GetConfigValue(_T("doesnot.exist"));
		}
		catch (char * libgiterr)
		{
			MessageBox(NULL, CString(libgiterr), _T("TortoiseGitBlame"), MB_ICONERROR);
			return FALSE;
		}

		CString cmd;
		cmd.Format(_T("git.exe blame -s -l %s -- \"%s\""),Rev,path.GetGitPathString());
		m_BlameData.clear();
		BYTE_VECTOR err;
		if(g_Git.Run(cmd, &m_BlameData, &err))
		{
			CString str;
			if (!m_BlameData.empty())
				g_Git.StringAppend(&str, &m_BlameData[0], CP_UTF8);
			if (!err.empty())
				g_Git.StringAppend(&str, &err[0], CP_UTF8);
			MessageBox(NULL, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK);

			return FALSE;
		}

		if(!m_TempFileName.IsEmpty())
		{
			::DeleteFile(m_TempFileName);
			m_TempFileName.Empty();
		}

		m_TempFileName=GetTempFile();

		cmd.Format(_T("git.exe cat-file blob %s:\"%s\""),Rev,path.GetGitPathString());

		if(g_Git.RunLogFile(cmd, m_TempFileName))
		{
			CString str;
			str.Format(IDS_CHECKOUTFAILED, path.GetGitPathString());
			MessageBox(NULL, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK);
			return FALSE;
		}

		m_GitPath = path;
		if (GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString(), m_Rev, (theApp.GetInt(_T("FollowRenames"), 0) == 1)))
			return FALSE;

		CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView());
		if(pView == NULL)
		{
			CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
			if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView)))
			{
				pView = (CTortoiseGitBlameView*)pWnd;
			}
			else
			{
				return FALSE;
			}
		}
		pView->UpdateInfo();
	}

	return TRUE;
}