Mercurial and Git clients can push and pull from this alias URL to interact with this repository. You can change to which repository an alias points by going to the Aliases link on the project page.
#include "stdafx.h"#include "ShellExt.h"#include "TortoiseUtils.h"#include "StringUtils.h"#include "Dirstatecache.h"#include "Thgstatus.h"typedefstruct{std::stringname;std::stringmenuText;std::stringhelpText;std::stringiconName;UINTidCmd;}MenuDescription;MenuDescriptionmenuDescList[]={{"commit","HG Commit...","Commit changes in repository","menucommit.ico",0},{"init","Create Repository Here","Create a new repository in this directory","menucreaterepos.ico",0},{"clone","Clone a Repository","Create clone here from source","menuclone.ico",0},{"status","View File Status","Repository status & changes","menushowchanged.ico",0},{"shelve","Shelve Changes","Shelve or unshelve file changes","shelve.ico",0},{"add","Add Files","Add files to version control","menuadd.ico",0},{"revert","Revert Files","Revert file changes","menurevert.ico",0},{"remove","Remove Files","Remove files from version control","menudelete.ico",0},{"rename","Rename File","Rename file or directory","general.ico",0},{"log","View Changelog","View change history in repository","menulog.ico",0},{"synch","Synchronize","Synchronize with remote repository","menusynch.ico",0},{"serve","Web Server","Start web server for this repository","proxy.ico",0},{"update","Update To Revision","Update working directory","menucheckout.ico",0},{"recover","Recovery...","General repair and recovery of repository","general.ico",0},{"thgstatus","Update Icons","Update icons for this repository","menumerge.ico",0},{"userconf","Global Settings","Configure user wide settings","settings_user.ico",0},{"repoconf","Repository Settings","Configure repository settings","settings_repo.ico",0},{"about","About...","Show About Dialog","menuabout.ico",0},{"datamine","Annotate Files","Show changeset information per file line","menublame.ico",0},{"vdiff","Visual Diff","View changes using GUI diff tool","TortoiseMerge.ico",0},/* Add new items here */// template{"","","",".ico",0},};/* These enumerations must match the order of menuDescList */enummenuDescListEntries{Commit,Init,Clone,Status,Shelve,Add,Revert,Remove,Rename,Log,Synch,Serve,Update,Recover,Thgstatus,Userconf,Repoconf,About,Datamine,VDiff,/* Add new items here */Separator,EndOfList};menuDescListEntriesRepoNoFilesMenu[]={Commit,Status,Shelve,VDiff,Separator,Log,Separator,Update,Separator,Synch,Clone,Recover,Serve,Thgstatus,Separator,Repoconf,Userconf,Separator,About,EndOfList};menuDescListEntriesRepoFilesMenu[]={Commit,Status,VDiff,Add,Revert,Rename,Remove,Separator,Log,Datamine,Separator,About,EndOfList};menuDescListEntriesNoRepoMenu[]={Clone,Init,Userconf,Thgstatus,Separator,About,EndOfList};typedefstd::map<std::string,MenuDescription>MenuDescriptionMap;typedefstd::map<UINT,MenuDescription>MenuIdCmdMap;MenuDescriptionMapMenuDescMap;MenuIdCmdMapMenuIdMap;voidAddMenuList(UINTidCmd,conststd::string&name){TDEBUG_TRACE("AddMenuList: idCmd = "<<idCmd<<" name = "<<name); MenuIdMap[idCmd] = MenuDescMap[name];
}
+void GetCMenuTranslation(+ const std::string& lang,+ const std::string& name,+ std::string& menuText,+ std::string& helpText)+{+ std::string subkey = "Software\\TortoiseHg\\CMenu\\";+ subkey += lang;+ subkey += "\\";+ subkey += name;++ TDEBUG_TRACE("GetCMenuTranslation: " << subkey);++ HKEY hkey = 0;+ LONG rv = RegOpenKeyExA(+ HKEY_CURRENT_USER, subkey.c_str(), 0, KEY_READ, &hkey);++ if (rv != ERROR_SUCCESS || hkey == 0)+ return;++ BYTE Data[MAX_PATH] = "";+ DWORD cbData = MAX_PATH * sizeof(BYTE);++ rv = RegQueryValueExA(hkey, "menuText", 0, 0, Data, &cbData);+ if (rv == ERROR_SUCCESS)+ menuText = reinterpret_cast<const char*>(&Data);++ rv = RegQueryValueExA(hkey, "helpText", 0, 0, Data, &cbData);+ if (rv == ERROR_SUCCESS)+ helpText = reinterpret_cast<const char*>(&Data);+}+void InitMenuMaps()
{
if (MenuDescMap.empty())
{
+ std::string lang;+ GetRegistryConfig("CMenuLang", lang);+ std::size_t sz = sizeof(menuDescList) / sizeof(MenuDescription);
for (std::size_t i=0; i < sz; i++)
{
MenuDescription md = menuDescList[i];
TDEBUG_TRACE("InitMenuMaps: adding " << md.name);
++ // Look for translation of menu and help text+ if( lang.size() )+ GetCMenuTranslation(lang, md.name, md.menuText, md.helpText);+ MenuDescMap[md.name] = md;
}
}
MenuIdMap.clear();}voidInsertMenuItemWithIcon(HMENUhMenu,UINTindexMenu,UINTidCmd,conststd::string&menuText,conststd::string&iconName){MENUITEMINFOmi;mi.cbSize=sizeof(mi);mi.dwTypeData=const_cast<char*>(menuText.c_str());mi.cch=static_cast<UINT>(menuText.length());mi.wID=idCmd;mi.fType=MFT_STRING;HICONh=GetTortoiseIcon(iconName);if(h){mi.fMask=MIIM_STRING|MIIM_FTYPE|MIIM_ID|MIIM_BITMAP|MIIM_DATA;mi.dwItemData=(ULONG_PTR)h;mi.hbmpItem=HBMMENU_CALLBACK;}else{TDEBUG_TRACE(" InsertMenuItemWithIcon: can't find "+iconName);mi.fMask=MIIM_TYPE|MIIM_ID;}InsertMenuItem(hMenu,indexMenu,TRUE,&mi);}voidInsertSubMenuItemWithIcon(HMENUhMenu,HMENUhSubMenu,UINTindexMenu,UINTidCmd,conststd::string&menuText,conststd::string&iconName){MENUITEMINFOmi;mi.cbSize=sizeof(mi);mi.fMask=MIIM_SUBMENU|MIIM_STRING|MIIM_ID;mi.fType=MFT_STRING;mi.dwTypeData=const_cast<char*>(menuText.c_str());mi.cch=static_cast<UINT>(menuText.length());mi.wID=idCmd;mi.hSubMenu=hSubMenu;HICONh=GetTortoiseIcon(iconName);if(h){mi.fMask=MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU|MIIM_ID|MIIM_BITMAP|MIIM_DATA;mi.dwItemData=(ULONG_PTR)h;mi.hbmpItem=HBMMENU_CALLBACK;}else{TDEBUG_TRACE(" InsertSubMenuItemWithIcon: can't find "+iconName);}InsertMenuItem(hMenu,indexMenu,TRUE,&mi);}voidInsertMenuItemByName(HMENUhMenu,conststd::string&name,UINTindexMenu,UINTidCmd,UINTidCmdFirst){TDEBUG_TRACE("InsertMenuItemByName: name = "<<name);MenuDescriptionMap::iteratoriter=MenuDescMap.find(name);if(iter==MenuDescMap.end()){TDEBUG_TRACE("InsertMenuItemByName: can't find menu info for "<<name);return;}MenuDescriptionmd=iter->second;AddMenuList(idCmd-idCmdFirst,name);InsertMenuItemWithIcon(hMenu,indexMenu,idCmd,md.menuText,md.iconName);}// IContextMenuSTDMETHODIMPCShellExt::QueryContextMenu(HMENUhMenu,UINTindexMenu,UINTidCmdFirst,UINTidCmdLast,UINTuFlags){TDEBUG_TRACE("CShellExt::QueryContextMenu");InitMenuMaps();UINTidCmd=idCmdFirst;BOOLbAppendItems=TRUE;if((uFlags&0x000F)==CMF_NORMAL)bAppendItems=TRUE;elseif(uFlags&CMF_VERBSONLY)bAppendItems=TRUE;elseif(uFlags&CMF_EXPLORE)bAppendItems=TRUE;elsebAppendItems=FALSE;if(!bAppendItems)returnNOERROR;conststd::size_tsz=sizeof(menuDescList)/sizeof(MenuDescription);boolpromoted[sz];memset(&promoted,0,sizeof(promoted));std::stringcval;GetRegistryConfig("PromotedItems",cval);size_tfound;do{if(cval.empty())break;found=cval.find_first_of(',');std::stringkey;if(found==std::string::npos)key=cval;else{key=cval.substr(0,found);cval=cval.substr(found+1);}for(UINTi=0;i<sz;i++){if(!key.compare(menuDescList[i].name)){promoted[i]=true;break;}}}while(found!=std::string::npos);// check if target directory is a Mercurial repositorystd::stringcwd;if(!myFolder.empty()){cwd=myFolder;}elseif(!myFiles.empty()){cwd=IsDirectory(myFiles[0])?myFiles[0]:DirName(myFiles[0]);}boolisHgrepo=false;if(!cwd.empty())isHgrepo=IsHgRepo(cwd);/* We have three menu types: files-selected, no-files-selected, no-repo */menuDescListEntries*entries;if(isHgrepo)if(myFiles.empty())entries=RepoNoFilesMenu;elseentries=RepoFilesMenu;elseentries=NoRepoMenu;// start building TortoiseHg menus and submenusInsertMenu(hMenu,indexMenu++,MF_SEPARATOR|MF_BYPOSITION,0,NULL);menuDescListEntries*walk;for(walk=entries;*walk!=EndOfList;walk++){UINTidx=(UINT)*walk;if(promoted[idx])InsertMenuItemByName(hMenu,menuDescList[idx].name,indexMenu++,idCmd++,idCmdFirst);}HMENUhSubMenu=CreatePopupMenu();if(hSubMenu){UINTindexSubMenu=0;for(walk=entries;*walk!=EndOfList;walk++){if(*walk==Separator)InsertMenu(hSubMenu,indexSubMenu++,MF_SEPARATOR|MF_BYPOSITION,0,NULL);else{UINTidx=(UINT)*walk;if(!promoted[idx])InsertMenuItemByName(hSubMenu,menuDescList[idx].name,indexSubMenu++,idCmd++,idCmdFirst);}}}TDEBUG_TRACE(" CShellExt::QueryContextMenu: adding main THG menu");InsertSubMenuItemWithIcon(hMenu,hSubMenu,indexMenu++,idCmd++,"TortoiseHG...","hg.ico");InsertMenu(hMenu,indexMenu++,MF_SEPARATOR|MF_BYPOSITION,0,NULL);returnResultFromShort(idCmd-idCmdFirst);}STDMETHODIMPCShellExt::InvokeCommand(LPCMINVOKECOMMANDINFOlpcmi){TDEBUG_TRACE("CShellExt::InvokeCommand");HRESULThr=E_INVALIDARG;if(!HIWORD(lpcmi->lpVerb)){UINTidCmd=LOWORD(lpcmi->lpVerb);TDEBUG_TRACE("CShellExt::InvokeCommand: idCmd = "<<idCmd);MenuIdCmdMap::iteratoriter=MenuIdMap.find(idCmd);if(iter!=MenuIdMap.end()){DoHgtk(iter->second.name);hr=NOERROR;}else{TDEBUG_TRACE("CShellExt::InvokeCommand: action not found for idCmd "<<idCmd);}}returnhr;}STDMETHODIMPCShellExt::GetCommandString(UINT_PTRidCmd,UINTuFlags,UINTFAR*reserved,LPSTRpszName,UINTcchMax){*pszName=0;char*psz;TDEBUG_TRACE("CShellExt::GetCommandString: idCmd = "<<idCmd);MenuIdCmdMap::iteratoriter=MenuIdMap.find(static_cast<UINT>(idCmd));if(iter!=MenuIdMap.end()){TDEBUG_TRACE("CShellExt::GetCommandString: name = "<<iter->second.name);psz=(char*)iter->second.helpText.c_str();}else{TDEBUG_TRACE("CShellExt::GetCommandString: can't find idCmd "<<idCmd);psz="";}wcscpy((wchar_t*)pszName,_WCSTR(psz));returnNOERROR;}STDMETHODIMPCShellExt::HandleMenuMsg(UINTuMsg,WPARAMwParam,LPARAMlParam){LRESULTres;returnHandleMenuMsg2(uMsg,wParam,lParam,&res);}STDMETHODIMPCShellExt::HandleMenuMsg2(UINTuMsg,WPARAMwParam,LPARAMlParam,LRESULT*pResult){TDEBUG_ENTER("CShellExt::HandleMenuMsg2");// A great tutorial on owner drawn menus in shell extension can be found// here: http://www.codeproject.com/shell/shellextguide7.aspLRESULTres;if(!pResult)pResult=&res;*pResult=FALSE;switch(uMsg){caseWM_MEASUREITEM:
{MEASUREITEMSTRUCT*lpmis=(MEASUREITEMSTRUCT*)lParam;if(lpmis==NULL)break;lpmis->itemWidth+=2;if(lpmis->itemHeight<16)lpmis->itemHeight=16;*pResult=TRUE;}break;caseWM_DRAWITEM:
{DRAWITEMSTRUCT*lpdis=(DRAWITEMSTRUCT*)lParam;if(!lpdis||(lpdis->CtlType!=ODT_MENU)||!lpdis->itemData)break;//not for a menuDrawIconEx(lpdis->hDC,lpdis->rcItem.left-16,lpdis->rcItem.top+(lpdis->rcItem.bottom-lpdis->rcItem.top-16)/2,(HICON)lpdis->itemData,16,16,0,0,DI_NORMAL);*pResult=TRUE;}break;default:returnNOERROR;}returnNOERROR;}#include "Winstat.h"voidCShellExt::DoHgtk(conststd::string&cmd){std::stringdir=GetTHgProgRoot();if(dir.empty()){TDEBUG_TRACE("DoHgtk: THG root is empty");return;}std::stringhgcmd=dir+"\\hgtk.exe";WIN32_FIND_DATAAdata;HANDLEhfind=FindFirstFileA(hgcmd.c_str(),&data);if(hfind==INVALID_HANDLE_VALUE)hgcmd=dir+"\\hgtk.cmd";elseFindClose(hfind);hgcmd=Quote(hgcmd)+" "+cmd;std::stringcwd;if(!myFolder.empty()){cwd=myFolder;}elseif(!myFiles.empty()){cwd=IsDirectory(myFiles[0])?myFiles[0]:DirName(myFiles[0]);std::stringtempfile=GetTemporaryFile();SECURITY_ATTRIBUTESsa;memset(&sa,0,sizeof(sa));sa.nLength=sizeof(sa);sa.bInheritHandle=TRUE;TDEBUG_TRACE("DoHgtk: temp file = "<<tempfile);HANDLEtempfileHandle=CreateFileA(tempfile.c_str(),GENERIC_WRITE,FILE_SHARE_READ,&sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);for(std::vector<std::string>::size_typei=0;i<myFiles.size();i++){DWORDdwWritten;TDEBUG_TRACE("DoHgtk: temp file adding "<<myFiles[i]);WriteFile(tempfileHandle,myFiles[i].c_str(),static_cast<DWORD>(myFiles[i].size()),&dwWritten,0);WriteFile(tempfileHandle,"\n",1,&dwWritten,0);}CloseHandle(tempfileHandle);hgcmd+=" --listfile "+Quote(tempfile);}else{TDEBUG_TRACE("DoHgtk: can't get cwd");return;}if(cmd=="thgstatus"){Thgstatus::remove(cwd);return;}LaunchCommand(hgcmd,cwd);}
Attach a Trello Card
Add a tag
Your session has expired
You are no longer logged in. Please log in and try your request again.
Filter RSS Feed
This RSS feed URL allows you to see the contents of your current filter using any feed reader.
This link includes a special authentication token. If you share the URL with anyone else, they can see this RSS feed's activity. You can disable these tokens when needed.
Your current filter is unsaved; changing it won't affect this RSS feed.