void CCommonAppUtils::SetWindowTitle( HWND hWnd, const CString& urlorpath, const CString& dialogname ) { #define MAX_PATH_LENGTH 80 ASSERT(dialogname.GetLength() < MAX_PATH_LENGTH); WCHAR pathbuf[MAX_PATH] = {0}; if (urlorpath.GetLength() >= MAX_PATH) { std::wstring str = (LPCTSTR)urlorpath; std::wregex rx(L"^(\\w+:|(?:\\\\|/+))((?:\\\\|/+)[^\\\\/]+(?:\\\\|/)[^\\\\/]+(?:\\\\|/)).*((?:\\\\|/)[^\\\\/]+(?:\\\\|/)[^\\\\/]+)$"); std::wstring replacement = L"$1$2...$3"; std::wstring str2 = std::regex_replace(str, rx, replacement); if (str2.size() >= MAX_PATH) str2 = str2.substr(0, MAX_PATH-2); PathCompactPathEx(pathbuf, str2.c_str(), MAX_PATH_LENGTH-dialogname.GetLength(), 0); } else PathCompactPathEx(pathbuf, urlorpath, MAX_PATH_LENGTH-dialogname.GetLength(), 0); CString title; switch (DWORD(CRegStdDWORD(L"Software\\TortoiseSVN\\DialogTitles", 0))) { case 0: // url/path - dialogname - appname title = pathbuf; title += L" - " + dialogname + L" - " + CString(MAKEINTRESOURCE(IDS_APPNAME)); break; case 1: // dialogname - url/path - appname title = dialogname + L" - " + pathbuf + L" - " + CString(MAKEINTRESOURCE(IDS_APPNAME)); break; } SetWindowText(hWnd, title); }
TCHAR *BuildMenuFileName(TCHAR *buffer, int len, int pos, const TCHAR *filename) { TCHAR cwd[MAX_PATH]; buffer[0] = 0; GetCurrentDirectory(_countof(cwd), cwd); lstrcat(cwd, TEXT("\\")); TCHAR *itr = buffer; TCHAR *end = buffer + len - 1; if (pos < 9) { *itr++ = '&'; *itr++ = '1' + (TCHAR)pos; } else if (pos == 9) { *itr++ = '1'; *itr++ = '&'; *itr++ = '0'; } else { wsprintf(itr, TEXT("%d"), pos+1); itr = itr + lstrlen(itr); } *itr++ = ':'; *itr++ = ' '; if (0 == generic_strnicmp(filename, cwd, lstrlen(cwd))) { TCHAR cnvName[MAX_PATH]; const TCHAR *s1 = PathFindFileName(filename); int len = lstrlen(s1); if (len < (end-itr)) { lstrcpy(cnvName, s1); } else { int n = (len-3-(itr-buffer))/2; generic_strncpy(cnvName, s1, n); lstrcpy(cnvName+n, TEXT("...")); lstrcat(cnvName, s1 + lstrlen(s1) - n); } convertFileName(itr, cnvName); } else { TCHAR cnvName[MAX_PATH*2]; convertFileName(cnvName, filename); PathCompactPathEx(itr, filename, len - (itr-buffer), 0); } return buffer; }
CString CWorkingFile::GetDescriptiveName() { if (m_sDescriptiveName.IsEmpty()) { CString sDescriptiveName = CPathUtils::GetFileNameFromPath(m_sFilename); WCHAR pathbuf[MAX_PATH] = {0}; PathCompactPathEx(pathbuf, sDescriptiveName, 50, 0); sDescriptiveName = pathbuf; return sDescriptiveName; } return m_sDescriptiveName; }
CString CFilePath::GetCompactStr( UINT unMax, DWORD dwFlags, DWORD dwEPPFlags) { CString sCleanPath = GetStr(dwEPPFlags); CString sRet; PathCompactPathEx(CStringLock(sRet, sCleanPath.GetLength()), sCleanPath, unMax, dwFlags); return sRet; }
// Build Recent File menu entries from given generic_string BuildMenuFileName(int filenameLen, unsigned int pos, const generic_string &filename) { generic_string strTemp; if (pos < 9) { strTemp.push_back('&'); strTemp.push_back('1' + (TCHAR)pos); } else if (pos == 9) { strTemp.append(TEXT("1&0")); } else { strTemp.append(uintToString(pos + 1)); } strTemp.append(TEXT(": ")); if (filenameLen > 0) { std::vector<TCHAR> vt(filenameLen + 1); //--FLS: W removed from PathCompactPathExW due to compiler errors for ANSI version. PathCompactPathEx(&vt[0], filename.c_str(), filenameLen + 1, 0); strTemp.append(convertFileName(vt.begin(), vt.begin() + lstrlen(&vt[0]))); } else { // (filenameLen < 0) generic_string::const_iterator it = filename.begin(); if (filenameLen == 0) it += PathFindFileName(filename.c_str()) - filename.c_str(); // MAX_PATH is still here to keep old trimming behaviour. if (filename.end() - it < MAX_PATH) { strTemp.append(convertFileName(it, filename.end())); } else { strTemp.append(convertFileName(it, it + MAX_PATH / 2 - 3)); strTemp.append(TEXT("...")); strTemp.append(convertFileName(filename.end() - MAX_PATH / 2, filename.end())); } } return strTemp; }
CString CStringUtils::WordWrap(const CString& longstring, int limit /* = 80 */, bool bCompactPaths /* = true */) { CString retString; if (longstring.GetLength() < limit) return longstring; // no wrapping needed. CString temp = longstring; while (temp.GetLength() > limit) { int pos=0; int oldpos=0; while ((pos>=0)&&(temp.Find(' ', pos)<limit)&&(temp.Find(' ', pos)>0)) { oldpos = pos; pos = temp.Find(' ', pos+1); } if (oldpos==0) oldpos = temp.Find(' '); if (pos<0) { retString += temp; temp.Empty(); } else { CString longline = oldpos >= 0 ? temp.Left(oldpos+1) : temp; if ((bCompactPaths)&&(longline.GetLength() < MAX_PATH)) { if (((!PathIsFileSpec(longline))&&longline.Find(':')<3)||(PathIsURL(longline))) { TCHAR buf[MAX_PATH]; PathCompactPathEx(buf, longline, limit+1, 0); longline = buf; } } retString += longline; if (oldpos >= 0) temp = temp.Mid(oldpos+1); else temp.Empty(); } retString += _T("\n"); pos = oldpos; } retString += temp; retString.Trim(); return retString; }
LPWSTR CBatchRunBtn::GetTipText(int tipID) { std::wstring strTip; for(int i = 0; i < m_progs.GetCount(); i++) { WCHAR out[MAX_PATH]; PathCompactPathEx(out, m_progs[i].fileName, 50, 0); if(i) { strTip += L"<br>"; } strTip += out; } LPWSTR name = (LPWSTR) CoTaskMemAlloc((strTip.length() + 1) * sizeof(WCHAR)); lstrcpy(name, strTip.c_str()); return name; }
bool SVNDiff::DiffProps(const CTSVNPath& filePath, const SVNRev& rev1, const SVNRev& rev2, svn_revnum_t &baseRev) const { bool retvalue = false; // diff the properties SVNProperties propswc(filePath, rev1, false, false); SVNProperties propsbase(filePath, rev2, false, false); #define MAX_PATH_LENGTH 80 WCHAR pathbuf1[MAX_PATH] = {0}; if (filePath.GetWinPathString().GetLength() >= MAX_PATH) { std::wstring str = filePath.GetWinPath(); std::wregex rx(L"^(\\w+:|(?:\\\\|/+))((?:\\\\|/+)[^\\\\/]+(?:\\\\|/)[^\\\\/]+(?:\\\\|/)).*((?:\\\\|/)[^\\\\/]+(?:\\\\|/)[^\\\\/]+)$"); std::wstring replacement = L"$1$2...$3"; std::wstring str2 = std::regex_replace(str, rx, replacement); if (str2.size() >= MAX_PATH) str2 = str2.substr(0, MAX_PATH-2); PathCompactPathEx(pathbuf1, str2.c_str(), MAX_PATH_LENGTH, 0); } else PathCompactPathEx(pathbuf1, filePath.GetWinPath(), MAX_PATH_LENGTH, 0); if ((baseRev == 0) && (!filePath.IsUrl()) && (rev1.IsBase() || rev2.IsBase())) { SVNStatus stat; CTSVNPath dummy; svn_client_status_t * s = stat.GetFirstFileStatus(filePath, dummy); if (s) baseRev = s->revision; } // check for properties that got removed for (int baseindex = 0; baseindex < propsbase.GetCount(); ++baseindex) { std::string basename = propsbase.GetItemName(baseindex); tstring basenameU = CUnicodeUtils::StdGetUnicode(basename); tstring basevalue = (LPCTSTR)CUnicodeUtils::GetUnicode(propsbase.GetItemValue(baseindex).c_str()); bool bFound = false; for (int wcindex = 0; wcindex < propswc.GetCount(); ++wcindex) { if (basename.compare (propswc.GetItemName(wcindex))==0) { bFound = true; break; } } if (!bFound) { // write the old property value to temporary file CTSVNPath wcpropfile = CTempFiles::Instance().GetTempFilePath(false); CTSVNPath basepropfile = CTempFiles::Instance().GetTempFilePath(false); FILE * pFile; _tfopen_s(&pFile, wcpropfile.GetWinPath(), L"wb"); if (pFile) { fclose(pFile); FILE * pFile2; _tfopen_s(&pFile2, basepropfile.GetWinPath(), L"wb"); if (pFile2) { fputs(CUnicodeUtils::StdGetUTF8(basevalue).c_str(), pFile2); fclose(pFile2); } else return false; } else return false; SetFileAttributes(wcpropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); SetFileAttributes(basepropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); CString n1, n2; bool bSwitch = false; if (rev1.IsWorking()) n1.Format(IDS_DIFF_PROP_WCNAME, basenameU.c_str()); if (rev1.IsBase()) { if (baseRev) n1.FormatMessage(IDS_DIFF_PROP_BASENAMEREV, basenameU.c_str(), baseRev); else n1.Format(IDS_DIFF_PROP_BASENAME, basenameU.c_str()); } if (rev1.IsHead()) n1.Format(IDS_DIFF_PROP_REMOTENAME, basenameU.c_str()); if (n1.IsEmpty()) { CString temp; temp.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev1); n1 = basenameU.c_str(); n1 += L" " + temp; bSwitch = true; } else { n1 = CString(pathbuf1) + L" - " + n1; } if (rev2.IsWorking()) n2.Format(IDS_DIFF_PROP_WCNAME, basenameU.c_str()); if (rev2.IsBase()) { if (baseRev) n2.FormatMessage(IDS_DIFF_PROP_BASENAMEREV, basenameU.c_str(), baseRev); else n2.Format(IDS_DIFF_PROP_BASENAME, basenameU.c_str()); } if (rev2.IsHead()) n2.Format(IDS_DIFF_PROP_REMOTENAME, basenameU.c_str()); if (n2.IsEmpty()) { CString temp; temp.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev2); n2 = basenameU.c_str(); n2 += L" " + temp; bSwitch = true; } else { n2 = CString(pathbuf1) + L" - " + n2; } if (bSwitch) { retvalue = !!CAppUtils::StartExtDiffProps(wcpropfile, basepropfile, n1, n2, TRUE, TRUE); } else { retvalue = !!CAppUtils::StartExtDiffProps(basepropfile, wcpropfile, n2, n1, TRUE, TRUE); } } } for (int wcindex = 0; wcindex < propswc.GetCount(); ++wcindex) { std::string wcname = propswc.GetItemName(wcindex); tstring wcnameU = CUnicodeUtils::StdGetUnicode(wcname); tstring wcvalue = (LPCTSTR)CUnicodeUtils::GetUnicode(propswc.GetItemValue(wcindex).c_str()); tstring basevalue; bool bDiffRequired = true; for (int baseindex = 0; baseindex < propsbase.GetCount(); ++baseindex) { if (propsbase.GetItemName(baseindex).compare(wcname)==0) { basevalue = CUnicodeUtils::GetUnicode(propsbase.GetItemValue(baseindex).c_str()); if (basevalue.compare(wcvalue)==0) { // name and value are identical bDiffRequired = false; break; } } } if (bDiffRequired) { // write both property values to temporary files CTSVNPath wcpropfile = CTempFiles::Instance().GetTempFilePath(false); CTSVNPath basepropfile = CTempFiles::Instance().GetTempFilePath(false); FILE * pFile; _tfopen_s(&pFile, wcpropfile.GetWinPath(), L"wb"); if (pFile) { fputs(CUnicodeUtils::StdGetUTF8(wcvalue).c_str(), pFile); fclose(pFile); FILE * pFile2; _tfopen_s(&pFile2, basepropfile.GetWinPath(), L"wb"); if (pFile2) { fputs(CUnicodeUtils::StdGetUTF8(basevalue).c_str(), pFile2); fclose(pFile2); } else return false; } else return false; SetFileAttributes(wcpropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); SetFileAttributes(basepropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); CString n1, n2; if (rev1.IsWorking()) n1.Format(IDS_DIFF_WCNAME, wcnameU.c_str()); if (rev1.IsBase()) n1.Format(IDS_DIFF_BASENAME, wcnameU.c_str()); if (rev1.IsHead()) n1.Format(IDS_DIFF_REMOTENAME, wcnameU.c_str()); if (n1.IsEmpty()) n1.FormatMessage(IDS_DIFF_PROP_REVISIONNAME, wcnameU.c_str(), (LPCTSTR)rev1.ToString()); else n1 = CString(pathbuf1) + L" - " + n1; if (rev2.IsWorking()) n2.Format(IDS_DIFF_WCNAME, wcnameU.c_str()); if (rev2.IsBase()) n2.Format(IDS_DIFF_BASENAME, wcnameU.c_str()); if (rev2.IsHead()) n2.Format(IDS_DIFF_REMOTENAME, wcnameU.c_str()); if (n2.IsEmpty()) n2.FormatMessage(IDS_DIFF_PROP_REVISIONNAME, wcnameU.c_str(), (LPCTSTR)rev2.ToString()); else n2 = CString(pathbuf1) + L" - " + n2; retvalue = !!CAppUtils::StartExtDiffProps(basepropfile, wcpropfile, n2, n1, TRUE, TRUE); } } return retvalue; }
CString CStringUtils::WordWrap(const CString& longstring, int limit, bool bCompactPaths, bool bForceWrap, int tabSize) { int nLength = longstring.GetLength(); CString retString; if (limit < 0) limit = 0; int nLineStart = 0; int nLineEnd = 0; int tabOffset = 0; for (int i = 0; i < nLength; ++i) { if (i-nLineStart+tabOffset >= limit) { if (nLineEnd == nLineStart) { if (bForceWrap) nLineEnd = i; else { while ((i < nLength) && (longstring[i] != ' ') && (longstring[i] != '\t')) ++i; nLineEnd = i; } } if (bCompactPaths) { CString longline = longstring.Mid(nLineStart, nLineEnd-nLineStart).Left(MAX_PATH-1); if ((bCompactPaths)&&(longline.GetLength() < MAX_PATH)) { if (((!PathIsFileSpec(longline))&&longline.Find(':')<3)||(PathIsURL(longline))) { TCHAR buf[MAX_PATH] = {0}; PathCompactPathEx(buf, longline, limit+1, 0); longline = buf; } } retString += longline; } else retString += longstring.Mid(nLineStart, nLineEnd-nLineStart); retString += L"\n"; tabOffset = 0; nLineStart = nLineEnd; } if (longstring[i] == ' ') nLineEnd = i; if (longstring[i] == '\t') { tabOffset += (tabSize - i % tabSize); nLineEnd = i; } } if (bCompactPaths) { CString longline = longstring.Mid(nLineStart).Left(MAX_PATH-1); if ((bCompactPaths)&&(longline.GetLength() < MAX_PATH)) { if (((!PathIsFileSpec(longline))&&longline.Find(':')<3)||(PathIsURL(longline))) { TCHAR buf[MAX_PATH] = {0}; PathCompactPathEx(buf, longline, limit+1, 0); longline = buf; } } retString += longline; } else retString += longstring.Mid(nLineStart); return retString; }
void CRepositoryBrowser::ShowContextMenu(CPoint point, TShadowFilesTreeList &selectedLeafs, eSelectionType selType) { CIconMenu popupMenu; popupMenu.CreatePopupMenu(); bool bAddSeparator = false; if (selectedLeafs.size() == 1) { popupMenu.AppendMenuIcon(eCmd_Open, IDS_REPOBROWSE_OPEN, IDI_OPEN); popupMenu.SetDefaultItem(eCmd_Open, FALSE); if (selType == ONLY_FILES || selType == ONLY_FILESSUBMODULES) { popupMenu.AppendMenuIcon(eCmd_OpenWith, IDS_LOG_POPUP_OPENWITH, IDI_OPEN); popupMenu.AppendMenuIcon(eCmd_OpenWithAlternativeEditor, IDS_LOG_POPUP_VIEWREV); } popupMenu.AppendMenu(MF_SEPARATOR); if (m_bHasWC && (selType == ONLY_FILES || selType == ONLY_FILESSUBMODULES)) { popupMenu.AppendMenuIcon(eCmd_CompareWC, IDS_LOG_POPUP_COMPARE, IDI_DIFF); bAddSeparator = true; } if (bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = false; CString temp; temp.LoadString(IDS_MENULOG); popupMenu.AppendMenuIcon(eCmd_ViewLog, temp, IDI_LOG); if (selectedLeafs[0]->m_bSubmodule) { temp.LoadString(IDS_MENULOGSUBMODULE); popupMenu.AppendMenuIcon(eCmd_ViewLogSubmodule, temp, IDI_LOG); } if (selType == ONLY_FILES) { if (m_bHasWC) popupMenu.AppendMenuIcon(eCmd_Blame, IDS_LOG_POPUP_BLAME, IDI_BLAME); popupMenu.AppendMenu(MF_SEPARATOR); temp.LoadString(IDS_LOG_POPUP_SAVE); popupMenu.AppendMenuIcon(eCmd_SaveAs, temp, IDI_SAVEAS); } bAddSeparator = true; } if (!selectedLeafs.empty() && selType == ONLY_FILES && m_bHasWC) { popupMenu.AppendMenuIcon(eCmd_Revert, IDS_LOG_POPUP_REVERTTOREV, IDI_REVERT); bAddSeparator = true; } if (bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = false; if (selectedLeafs.size() == 1 && selType == ONLY_FILES) { popupMenu.AppendMenuIcon(eCmd_PrepareDiff, IDS_PREPAREDIFF, IDI_DIFF); if (!m_sMarkForDiffFilename.IsEmpty()) { CString diffWith; if (selectedLeafs.at(0)->GetFullName() == m_sMarkForDiffFilename) diffWith = m_sMarkForDiffVersion; else { PathCompactPathEx(diffWith.GetBuffer(40), m_sMarkForDiffFilename, 39, 0); diffWith.ReleaseBuffer(); diffWith += _T(":") + m_sMarkForDiffVersion.ToString().Left(g_Git.GetShortHASHLength()); } CString menuEntry; menuEntry.Format(IDS_MENUDIFFNOW, (LPCTSTR)diffWith); popupMenu.AppendMenuIcon(eCmd_PrepareDiff_Compare, menuEntry, IDI_DIFF); } popupMenu.AppendMenu(MF_SEPARATOR); } if (!selectedLeafs.empty()) { popupMenu.AppendMenuIcon(eCmd_CopyPath, IDS_STATUSLIST_CONTEXT_COPY, IDI_COPYCLIP); popupMenu.AppendMenuIcon(eCmd_CopyHash, IDS_COPY_COMMIT_HASH, IDI_COPYCLIP); } eCmd cmd = (eCmd)popupMenu.TrackPopupMenuEx(TPM_LEFTALIGN|TPM_RETURNCMD, point.x, point.y, this, 0); switch(cmd) { case eCmd_ViewLog: case eCmd_ViewLogSubmodule: { CString sCmd; sCmd.Format(_T("/command:log /path:\"%s\\%s\""), (LPCTSTR)g_Git.m_CurrentDir, (LPCTSTR)selectedLeafs.at(0)->GetFullName()); if (cmd == eCmd_ViewLog && selectedLeafs.at(0)->m_bSubmodule) sCmd += _T(" /submodule"); CAppUtils::RunTortoiseGitProc(sCmd); } break; case eCmd_Blame: { CAppUtils::LaunchTortoiseBlame(g_Git.CombinePath(selectedLeafs.at(0)->GetFullName()), m_sRevision); } break; case eCmd_Open: if (!selectedLeafs.at(0)->m_bSubmodule && selectedLeafs.at(0)->m_bFolder) { FillListCtrlForTreeNode(selectedLeafs.at(0)->m_hTree); m_RepoTree.SelectItem(selectedLeafs.at(0)->m_hTree); return; } OpenFile(selectedLeafs.at(0)->GetFullName(), OPEN, selectedLeafs.at(0)->m_bSubmodule, selectedLeafs.at(0)->m_hash); break; case eCmd_OpenWith: OpenFile(selectedLeafs.at(0)->GetFullName(), OPEN_WITH, selectedLeafs.at(0)->m_bSubmodule, selectedLeafs.at(0)->m_hash); break; case eCmd_OpenWithAlternativeEditor: OpenFile(selectedLeafs.at(0)->GetFullName(), ALTERNATIVEEDITOR, selectedLeafs.at(0)->m_bSubmodule, selectedLeafs.at(0)->m_hash); break; case eCmd_CompareWC: { CTGitPath file(selectedLeafs.at(0)->GetFullName()); CGitDiff::Diff(&file, &file, GIT_REV_ZERO, m_sRevision); } break; case eCmd_Revert: { int count = 0; for (TShadowFilesTreeList::iterator itShadowTree = selectedLeafs.begin(); itShadowTree != selectedLeafs.end(); ++itShadowTree) { if (RevertItemToVersion((*itShadowTree)->GetFullName())) ++count; else break; } CString msg; msg.Format(IDS_STATUSLIST_FILESREVERTED, count, (LPCTSTR)m_sRevision); MessageBox(msg, _T("TortoiseGit"), MB_OK); } break; case eCmd_SaveAs: FileSaveAs(selectedLeafs.at(0)->GetFullName()); break; case eCmd_CopyPath: { CString sClipboard; for (TShadowFilesTreeList::iterator itShadowTree = selectedLeafs.begin(); itShadowTree != selectedLeafs.end(); ++itShadowTree) { sClipboard += (*itShadowTree)->m_sName + _T("\r\n"); } CStringUtils::WriteAsciiStringToClipboard(sClipboard); } break; case eCmd_CopyHash: { CopyHashToClipboard(selectedLeafs); } break; case eCmd_PrepareDiff: m_sMarkForDiffFilename = selectedLeafs.at(0)->GetFullName(); if (g_Git.GetHash(m_sMarkForDiffVersion, m_sRevision)) { m_sMarkForDiffFilename.Empty(); MessageBox(g_Git.GetGitLastErr(_T("Could not get SHA-1 for ") + m_sRevision), _T("TortoiseGit"), MB_ICONERROR); } break; case eCmd_PrepareDiff_Compare: { CTGitPath savedFile(m_sMarkForDiffFilename); CTGitPath selectedFile(selectedLeafs.at(0)->GetFullName()); CGitHash currentHash; if (g_Git.GetHash(currentHash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get SHA-1 for ") + m_sRevision), _T("TortoiseGit"), MB_ICONERROR); return; } CGitDiff::Diff(&selectedFile, &savedFile, currentHash, m_sMarkForDiffVersion); } break; } }
//--------------------------------------------------------------------------- static String CompactPath(const String &Path, unsigned MaxLen) { std::vector<wchar_t> Str(MaxLen + 1); PathCompactPathEx(&Str[0], Path.c_str(), MaxLen+1, 0); return &Str[0]; }