[PATCH 0 of 1] Fix Windows shellext 0x5c problem of Japanese shift-jis and Chinese(Taiwanese) big5.

54 views
Skip to first unread message

Toshi MARUYAMA

unread,
Jul 18, 2011, 6:48:32 PM7/18/11
to thg...@googlegroups.com
I am maintaining my Windows shellext Unicode poriting from Sep 2010.
http://groups.google.com/group/thg-dev/browse_thread/thread/dd3339f9b2665ee9

Many users use it and there is no bug report.
https://bitbucket.org/marutosi/tortoisehg/downloads

win32mbcs extension is distributed with Mercurial.
It seems Matt will refactor Windows filename Unicode scheme.

Mercurial-devel ML Jul 6, 2011
Re: [PATCH] win32mbcs: wrap two more functions
http://markmail.org/message/6o3vkt2fw66syrws
> We might want to investigate a scheme like the localstr class
> in encoding.py to isolate Mercurial from this weirdness
> while still allowing Unicode filenames.

1.9 Sprint
http://titanpad.com/mercurial19
Line 131:
> fixutf8
> * mpm: *I proposed this*
> * eventually this should be in core
> * probably need more tests to discuss shift-jis support
> backslashes appear in the second byte of characters
> which can confuse things


My fork supports both of win32mbcs and fixutf8 extensions.
But, this patch drops fixutf8 supporting and only supports win32mbcs.
I will continue to maintain my fork for fixutf8.

Because win32mbcs extension is distributed with Mercurial,
I wish to apply this patch to thg main stream.

Toshi MARUYAMA

unread,
Jul 18, 2011, 6:48:33 PM7/18/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311028778 -32400
# Branch stable
# Node ID 6d22b009dbbe252a0f081b74830090c1c803280b
# Parent 8574a69622d39c35640b1eb8a5363e3aaac0ff57
shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)

Issue #1241.

Merge squashed following jobs.
* Marco Lizza's patches exclude tortoisehg_rev6547.patch (Msi.lib).
http://groups.google.com/group/thg-dev/browse_thread/thread/8580c791fe5b52b2
* Tinyfish's Unicode porting.
http://bitbucket.org/tinyfish/tortoisehg.winutf8/changeset/cdce65b00f1e

diff --git a/win32/shellext/CShellExtCMenu.cpp b/win32/shellext/CShellExtCMenu.cpp
--- a/win32/shellext/CShellExtCMenu.cpp
+++ b/win32/shellext/CShellExtCMenu.cpp
@@ -14,135 +14,147 @@

#include "CShellExtCMenu.h"

+#define THG_FILENAME L"thgw"
+#define HGTK_FILENAME L"hgtk"
+
+#define LISTFILE_OPT_ACP L" --listfile "
+#define LISTFILE_CP_ACP CP_ACP
+
+#define LISTFILE_OPT_UTF8 L" --listfileutf8 "
+#define LISTFILE_CP_UTF8 CP_UTF8
+
+const std::wstring TortoiseHgMenuEntryString = L"TortoiseHg";
+
// According to http://msdn.microsoft.com/en-us/library/bb776094%28VS.85%29.aspx
// the help texts for the commands should be reasonably short (under 40 characters)

static const MenuDescription CMenuMenuDescList[] =
{
- {"commit", L"Commit...",
+ {L"commit", L"Commit...",
L"Commit changes in repository",
- "menucommit.ico", 0},
- {"init", L"Create Repository Here",
+ L"menucommit.ico", 0},
+ {L"init", L"Create Repository Here",
L"Create a new repository",
- "menucreaterepos.ico", 0},
- {"clone", L"Clone...",
+ L"menucreaterepos.ico", 0},
+ {L"clone", L"Clone...",
L"Create clone here from source",
- "menuclone.ico", 0},
- {"shelve", L"Shelve Changes",
+ L"menuclone.ico", 0},
+ {L"shelve", L"Shelve Changes",
L"Shelve or unshelve file changes",
- "shelve.ico", 0},
- {"status", L"View File Status",
+ L"shelve.ico", 0},
+ {L"status", L"View File Status",
L"Repository status & changes",
- "menushowchanged.ico", 0},
- {"add", L"Add Files...",
+ L"menushowchanged.ico", 0},
+ {L"add", L"Add Files...",
L"Add files to version control",
- "menuadd.ico", 0},
- {"revert", L"Revert Files...",
+ L"menuadd.ico", 0},
+ {L"revert", L"Revert Files...",
L"Revert file changes",
- "menurevert.ico", 0},
- {"remove", L"Remove Files...",
+ L"menurevert.ico", 0},
+ {L"remove", L"Remove Files...",
L"Remove files from version control",
- "menudelete.ico", 0},
- {"rename", L"Rename File...",
+ L"menudelete.ico", 0},
+ {L"rename", L"Rename File...",
L"Rename file or directory",
- "general.ico", 0},
- {"workbench", L"Workbench",
+ L"general.ico", 0},
+ {L"workbench", L"Workbench",
L"View change history of repository",
- "menulog.ico", 0},
- {"log", L"Revision History",
+ L"menulog.ico", 0},
+ {L"log", L"Revision History",
L"View change history of selected files",
- "menulog.ico", 0},
- {"synch", L"Synchronize",
+ L"menulog.ico", 0},
+ {L"synch", L"Synchronize",
L"Synchronize with remote repository",
- "menusynch.ico", 0},
- {"serve", L"Web Server",
+ L"menusynch.ico", 0},
+ {L"serve", L"Web Server",
L"Start web server for this repository",
- "proxy.ico", 0},
- {"update", L"Update...",
+ L"proxy.ico", 0},
+ {L"update", L"Update...",
L"Update working directory",
- "menucheckout.ico", 0},
- {"thgstatus", L"Update Icons",
+ L"menucheckout.ico", 0},
+ {L"thgstatus", L"Update Icons",
L"Update icons for this repository",
- "refresh_overlays.ico", 0},
- {"userconf", L"Global Settings",
+ L"refresh_overlays.ico", 0},
+ {L"userconf", L"Global Settings",
L"Configure user wide settings",
- "settings_user.ico", 0},
- {"repoconf", L"Repository Settings",
+ L"settings_user.ico", 0},
+ {L"repoconf", L"Repository Settings",
L"Configure repository settings",
- "settings_repo.ico", 0},
- {"about", L"About TortoiseHg",
+ L"settings_repo.ico", 0},
+ {L"about", L"About TortoiseHg",
L"Show About Dialog",
- "menuabout.ico", 0},
- {"annotate", L"Annotate Files",
+ L"menuabout.ico", 0},
+ {L"annotate", L"Annotate Files",
L"Changeset information per file line",
- "menublame.ico", 0},
- {"vdiff", L"Visual Diff",
+ L"menublame.ico", 0},
+ {L"vdiff", L"Visual Diff",
L"View changes using GUI diff tool",
- "TortoiseMerge.ico", 0},
- {"hgignore", L"Edit Ignore Filter",
+ L"TortoiseMerge.ico", 0},
+ {L"hgignore", L"Edit Ignore Filter",
L"Edit repository ignore filter",
- "ignore.ico", 0},
- {"guess", L"Guess Renames",
+ L"ignore.ico", 0},
+ {L"guess", L"Guess Renames",
L"Detect renames and copies",
- "detect_rename.ico", 0},
- {"grep", L"Search History",
+ L"detect_rename.ico", 0},
+ {L"grep", L"Search History",
L"Search file revisions for patterns",
- "menurepobrowse.ico", 0},
- {"forget", L"Forget Files...",
+ L"menurepobrowse.ico", 0},
+ {L"forget", L"Forget Files...",
L"Remove files from version control",
- "menudelete.ico", 0},
- {"shellconf", L"Explorer Extension Settings",
+ L"menudelete.ico", 0},
+ {L"shellconf", L"Explorer Extension Settings",
L"Configure Explorer extension",
- "settings_repo.ico", 0},
+ L"settings_repo.ico", 0},
+ {L"tortoisehg", TortoiseHgMenuEntryString,
+ L"Tortoise Hg",
+ L"hg.ico", 0},

/* Add new items here */

// template
- //{"", L"", L"", ".ico", 0},
+ //{L"", L"", L"", ".ico", 0},
};

-static const char* const RepoNoFilesMenu =
- "commit status shelve vdiff sep"
- " add revert rename forget remove sep"
- " workbench update grep sep"
- " synch serve clone init thgstatus sep"
- " hgignore guess sep"
- " shellconf repoconf userconf sep"
- " about"
+const wchar_t* const RepoNoFilesMenu =
+ L"commit status shelve vdiff sep"
+ L" add revert rename forget remove sep"
+ L" workbench update grep sep"
+ L" synch serve clone init thgstatus sep"
+ L" hgignore guess sep"
+ L" shellconf repoconf userconf sep"
+ L" about"
;

-static const char* const RepoFilesMenu =
- "commit status vdiff sep"
- " add revert rename forget remove sep"
- " log annotate sep"
- " about"
+static const wchar_t* const RepoFilesMenu =
+ L"commit status vdiff sep"
+ L" add revert rename forget remove sep"
+ L" log annotate sep"
+ L" about"
;

-static const char* const NoRepoMenu =
- "clone init shellconf userconf thgstatus sep"
- " workbench sep"
- " about"
+static const wchar_t* const NoRepoMenu =
+ L"clone init shellconf userconf thgstatus sep"
+ L" workbench sep"
+ L" about"
;

-
-void CShellExtCMenu::AddMenuList(UINT idCmd, const std::string& name)
+void CShellExtCMenu::AddMenuList(UINT idCmd, const std::wstring& name)
{
- TDEBUG_TRACE("AddMenuList: idCmd = " << idCmd << " name = " << name);
+ TDEBUG_TRACEW(L"AddMenuList: idCmd = " << idCmd << L" name = " << name);
myMenuIdMap[idCmd] = myDescMap[name];
}

-
void GetCMenuTranslation(
- const std::string& lang,
- const std::string& name,
- std::wstring& menuText,
- std::wstring& helpText
+ const std::wstring& lang,
+ const std::wstring& name,
+ std::wstring& menuText,
+ std::wstring& helpText
)
{
std::wstring subkey = L"Software\\TortoiseHg\\CMenu\\";
- subkey += _WCSTR(lang.c_str());
+ subkey += lang;
subkey += L"\\";
- subkey += _WCSTR(name.c_str());
+ subkey += name;

TDEBUG_TRACEW(L"GetCMenuTranslation: " << subkey);

@@ -171,8 +183,8 @@ void CShellExtCMenu::InitMenuMaps(const
{
if (myDescMap.empty())
{
- std::string lang;
- GetRegistryConfig("CMenuLang", lang);
+ std::wstring lang;
+ GetRegistryConfig(L"CMenuLang", lang);

for (std::size_t i = 0; i < sz; i++)
{
@@ -180,11 +192,11 @@ void CShellExtCMenu::InitMenuMaps(const

if (md.name.empty())
{
- TDEBUG_TRACE("**** InitMenuMaps: ignoring entry with empty name");
+ TDEBUG_TRACEW(L"**** InitMenuMaps: ignoring entry with empty name");
break;
}

- TDEBUG_TRACE("InitMenuMaps: adding " << md.name);
+ TDEBUG_TRACEW(L"InitMenuMaps: adding " << md.name);

// Look for translation of menu and help text
if (!lang.empty())
@@ -201,7 +213,7 @@ void CShellExtCMenu::InitMenuMaps(const

void InsertMenuItemWithIcon1(
HMENU hMenu, UINT indexMenu, UINT idCmd,
- const std::wstring& menuText, const std::string& iconName)
+ const std::wstring& menuText, const std::wstring& iconName)
{
// MFT_STRING is obsolete and should not be used (replaced by MIIM_STRING
// from Win2K onward)
@@ -223,7 +235,7 @@ void InsertMenuItemWithIcon1(
}
else
{
- TDEBUG_TRACE(" ***** InsertMenuItemWithIcon1: can't find " + iconName);
+ TDEBUG_TRACEW(L" ***** InsertMenuItemWithIcon1: can't find " + iconName);
}
}
else
@@ -237,7 +249,7 @@ void InsertMenuItemWithIcon1(
}
else
{
- TDEBUG_TRACE(" ***** InsertMenuItemWithIcon1: can't find " + iconName);
+ TDEBUG_TRACEW(L" ***** InsertMenuItemWithIcon1: can't find " + iconName);
}
}
InsertMenuItemW(hMenu, indexMenu, TRUE, &mi);
@@ -249,7 +261,7 @@ void InsertMenuItemWithIcon1(

void InsertSubMenuItemWithIcon2(
HMENU hMenu, HMENU hSubMenu, UINT indexMenu, UINT idCmd,
- const std::wstring& menuText, const std::string& iconName)
+ const std::wstring& menuText, const std::wstring& iconName)
{
// MFT_STRING is obsolete and should not be used (replaced by MIIM_STRING
// from Win2K onward)
@@ -272,7 +284,7 @@ void InsertSubMenuItemWithIcon2(
}
else
{
- TDEBUG_TRACE(" ***** InsertSubMenuItemWithIcon2: can't find " + iconName);
+ TDEBUG_TRACEW(L" ***** InsertSubMenuItemWithIcon2: can't find " + iconName);
}
}
else
@@ -286,38 +298,34 @@ void InsertSubMenuItemWithIcon2(
}
else
{
- TDEBUG_TRACE(" ***** InsertSubMenuItemWithIcon2: can't find " + iconName);
+ TDEBUG_TRACEW(L" ***** InsertSubMenuItemWithIcon2: can't find " + iconName);
}
}

InsertMenuItemW(hMenu, indexMenu, TRUE, &mi);

TDEBUG_TRACEW(
- L"InsertMenuItemWithIcon2(\"" << menuText << L"\") finished");
+ L"InsertSubMenuItemWithIcon2(\"" << menuText << L"\") finished");
}


void CShellExtCMenu::InsertMenuItemByName(
- HMENU hMenu, const std::string& name, UINT indexMenu,
+ HMENU hMenu, const std::wstring& name, UINT indexMenu,
UINT idCmd, UINT idCmdFirst, const std::wstring& prefix)
{
MenuDescriptionMap::iterator iter = myDescMap.find(name);
if (iter == myDescMap.end())
{
- TDEBUG_TRACE("***** InsertMenuItemByName: can't find menu info for " << name);
+ TDEBUG_TRACEW(L"***** InsertMenuItemByName: can't find menu info for " << name);
return;
}

-
MenuDescription md = iter->second;
AddMenuList(idCmd - idCmdFirst, name);
InsertMenuItemWithIcon1(
hMenu, indexMenu, idCmd, prefix + md.menuText, md.iconName);
}

-
-const std::wstring TortoiseHgMenuEntryString = L"TortoiseHg";
-
int HasTortoiseMenu(HMENU hMenu, bool& hasmenu)
// returns -1 on error, 0 otherwise
{
@@ -326,7 +334,7 @@ int HasTortoiseMenu(HMENU hMenu, bool& h
const int count = ::GetMenuItemCount(hMenu);
if (count == -1)
{
- TDEBUG_TRACE("***** HasTortoiseMenu: GetMenuItemCount returned -1");
+ TDEBUG_TRACEW(L"***** HasTortoiseMenu: GetMenuItemCount returned -1");
return -1;
}

@@ -340,7 +348,7 @@ int HasTortoiseMenu(HMENU hMenu, bool& h
mii.fMask = MIIM_STRING;
BOOL res = ::GetMenuItemInfoW(hMenu, i, true, &mii);
if (res == 0) {
- TDEBUG_TRACE("HasTortoiseMenu: "
+ TDEBUG_TRACEW(L"HasTortoiseMenu: "
<< "first GetMenuItemInfo returned 0");
continue;
}
@@ -359,7 +367,7 @@ int HasTortoiseMenu(HMENU hMenu, bool& h
++mii.cch; // size of buffer is one more than length of string
res = ::GetMenuItemInfoW(hMenu, i, true, &mii);
if (res == 0) {
- TDEBUG_TRACE("HasTortoiseMenu: "
+ TDEBUG_TRACEW(L"HasTortoiseMenu: "
<< "second GetMenuItemInfo returned 0");
continue;
}
@@ -370,13 +378,13 @@ int HasTortoiseMenu(HMENU hMenu, bool& h

if (menuitemtext == TortoiseHgMenuEntryString)
{
- TDEBUG_TRACE("HasTortoiseMenu: FOUND TortoiseHg menu entry");
+ TDEBUG_TRACEW(L"HasTortoiseMenu: FOUND TortoiseHg menu entry");
hasmenu = true;
return 0;
}
}

- TDEBUG_TRACE("HasTortoiseMenu: TortoiseHg menu entry NOT found");
+ TDEBUG_TRACEW(L"HasTortoiseMenu: TortoiseHg menu entry NOT found");
return 0;
}

@@ -396,12 +404,61 @@ CShellExtCMenu::TweakMenuForVista(HMENU

#define ResultFromShort(i) ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(i)))

+bool IsSpecialFolder(const std::wstring &folder)
+{
+ static int pCSIDL[] =
+ {
+ CSIDL_BITBUCKET,
+ CSIDL_CDBURN_AREA,
+ CSIDL_COMMON_STARTMENU,
+ CSIDL_COMPUTERSNEARME,
+ CSIDL_CONNECTIONS,
+ CSIDL_CONTROLS,
+ CSIDL_COOKIES,
+ CSIDL_FONTS,
+ CSIDL_HISTORY,
+ CSIDL_INTERNET,
+ CSIDL_INTERNET_CACHE,
+ CSIDL_NETHOOD,
+ CSIDL_NETWORK,
+ CSIDL_PRINTERS,
+ CSIDL_PRINTHOOD,
+ CSIDL_RECENT,
+ CSIDL_SENDTO,
+ CSIDL_STARTMENU,
+ 0
+ };
+
+ TDEBUG_TRACEW(L"IsSpecialFolder");
+ for (int i = 0; pCSIDL[i] != 0; i++)
+ {
+ LPITEMIDLIST pIDL = NULL;
+ if (SHGetSpecialFolderLocation(NULL, pCSIDL[i], &pIDL) != S_OK)
+ continue;
+
+ WCHAR tszPath[MAX_PATH + 1] = { L'\0' };
+ BOOL bResult = SHGetPathFromIDList(pIDL, tszPath);
+
+ CoTaskMemFree(pIDL);
+
+ if ((bResult == FALSE) || (tszPath[0] == L'\0'))
+ continue;
+
+ if (_wcsicmp(tszPath, folder.c_str())==0)
+ {
+ TDEBUG_TRACEW(L" folder '" << folder << L"' is special");
+ return true;
+ }
+ }
+ return false;
+}
+
// IContextMenu
STDMETHODIMP
CShellExtCMenu::QueryContextMenu(
HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
- TDEBUG_TRACE("CShellExtCMenu::QueryContextMenu");
+ TDEBUG_TRACEW(L"CShellExtCMenu::QueryContextMenu");

UINT idCmd = idCmdFirst;
BOOL bAppendItems = TRUE;
@@ -421,26 +478,26 @@ CShellExtCMenu::QueryContextMenu(
bool hasthgmenu = false;
if (HasTortoiseMenu(hMenu, hasthgmenu) == 0 && hasthgmenu)
{
- TDEBUG_TRACE("CShellExtCMenu::QueryContextMenu: "
+ TDEBUG_TRACEW(L"CShellExtCMenu::QueryContextMenu: "
<< "TortoiseHg menu entry already in menu -> skipping");
return S_OK;
}

InitMenuMaps(CMenuMenuDescList, sizeof(CMenuMenuDescList) / sizeof(MenuDescription));

- typedef std::vector<std::string> entriesT;
+ typedef std::vector<std::wstring> entriesT;
typedef entriesT::const_iterator entriesIter;

- std::string promoted_string = "commit,workbench"; // default value if key not found
- GetRegistryConfig("PromotedItems", promoted_string);
+ std::wstring promoted_string = L"commit,workbench"; // default value if key not found
+ GetRegistryConfig(L"PromotedItems", promoted_string);

entriesT promoted;
- Tokenize(promoted_string, promoted, ",");
+ Tokenize(promoted_string, promoted, L",");

// Select menu to show
bool fileMenu = !myFiles.empty();
bool isHgrepo = false;
- std::string cwd;
+ std::wstring cwd;
if (!myFolder.empty())
{
cwd = myFolder;
@@ -450,10 +507,17 @@ CShellExtCMenu::QueryContextMenu(
cwd = IsDirectory(myFiles[0])? myFiles[0] : DirName(myFiles[0]);
}

+ if (IsSpecialFolder(cwd))
+ {
+ // disable context menu if in a special folder
+ TDEBUG_TRACEW(L" shell-extension not available in this folder");
+ return S_OK;
+ }
+
if (!cwd.empty())
{
// check if target directory is a Mercurial repository
- std::string root = GetHgRepoRoot(cwd);
+ std::wstring root = GetHgRepoRoot(cwd);
isHgrepo = !root.empty();
if (myFiles.size() == 1 && root == myFiles[0])
{
@@ -469,21 +533,21 @@ CShellExtCMenu::QueryContextMenu(
if (!isHgrepo)
{
// we are not inside a repo
- std::string cval;
- if (GetRegistryConfig("HideMenuOutsideRepo", cval) != 0 && cval == "1")
+ std::wstring cval;
+ if (GetRegistryConfig(L"HideMenuOutsideRepo", cval) != 0 && cval == L"1")
{
return S_OK; // don't show thg cmenu entries
}
}
}

- TDEBUG_TRACE(
- "CShellExtCMenu::QueryContextMenu: isHgrepo = "
- << isHgrepo << ", fileMenu = " << fileMenu
+ TDEBUG_TRACEW(
+ L"CShellExtCMenu::QueryContextMenu: isHgrepo = "
+ << isHgrepo << L", fileMenu = " << fileMenu
);

/* We have three menu types: files-selected, no-files-selected, no-repo */
- const char* entries_string = 0;
+ const wchar_t* entries_string = 0;
if (isHgrepo)
if (fileMenu)
entries_string = RepoFilesMenu;
@@ -496,11 +560,11 @@ CShellExtCMenu::QueryContextMenu(
InsertMenu(hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);

entriesT entries;
- Tokenize(entries_string, entries, " ");
+ Tokenize(entries_string, entries, L" ");

for (entriesIter i = entries.begin(); i != entries.end(); i++)
{
- std::string name = *i;
+ std::wstring name = *i;
if (contains(promoted, name))
{
InsertMenuItemByName(
@@ -517,8 +581,8 @@ CShellExtCMenu::QueryContextMenu(
bool isSeparator = true;
for (entriesIter i = entries.begin(); i != entries.end(); i++)
{
- std::string name = *i;
- if (name == "sep")
+ std::wstring name = *i;
+ if (name == L"sep")
{
if (!isSeparator)
{
@@ -548,9 +612,9 @@ CShellExtCMenu::QueryContextMenu(

}

- TDEBUG_TRACE(" CShellExtCMenu::QueryContextMenu: adding main THG menu");
+ TDEBUG_TRACEW(L" CShellExtCMenu::QueryContextMenu: adding main THG menu");
InsertSubMenuItemWithIcon2(hMenu, hSubMenu, indexMenu++, idCmd++,
- TortoiseHgMenuEntryString, "hg.ico");
+ TortoiseHgMenuEntryString, L"hg.ico");

InsertMenu(hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);

@@ -565,13 +629,13 @@ CShellExtCMenu::QueryContextMenu(
STDMETHODIMP
CShellExtCMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
- TDEBUG_TRACE("CShellExtCMenu::InvokeCommand");
+ TDEBUG_TRACEW(L"CShellExtCMenu::InvokeCommand");

HRESULT hr = E_INVALIDARG;
if (!HIWORD(lpcmi->lpVerb))
{
UINT idCmd = LOWORD(lpcmi->lpVerb);
- TDEBUG_TRACE("CShellExtCMenu::InvokeCommand: idCmd = " << idCmd);
+ TDEBUG_TRACEW(L"CShellExtCMenu::InvokeCommand: idCmd = " << idCmd);
MenuIdCmdMap::iterator iter = myMenuIdMap.find(idCmd);
if (iter != myMenuIdMap.end())
{
@@ -580,8 +644,8 @@ CShellExtCMenu::InvokeCommand(LPCMINVOKE
}
else
{
- TDEBUG_TRACE(
- "***** CShellExtCMenu::InvokeCommand: action not found for idCmd "
+ TDEBUG_TRACEW(
+ L"***** CShellExtCMenu::InvokeCommand: action not found for idCmd "
<< idCmd
);
}
@@ -602,38 +666,38 @@ CShellExtCMenu::GetCommandString(
const char* psz = "";
const wchar_t* pszw = 0;

- std::string sflags = "?";
+ std::wstring sflags = L"?";
switch (uFlags)
{
case GCS_HELPTEXTW:
- sflags = "GCS_HELPTEXTW"; break;
+ sflags = L"GCS_HELPTEXTW"; break;
case GCS_HELPTEXTA:
- sflags = "GCS_HELPTEXTA"; break;
+ sflags = L"GCS_HELPTEXTA"; break;
case GCS_VALIDATEW:
- sflags = "GCS_VALIDATEW"; break;
+ sflags = L"GCS_VALIDATEW"; break;
case GCS_VALIDATEA:
- sflags = "GCS_VALIDATEA"; break;
+ sflags = L"GCS_VALIDATEA"; break;
case GCS_VERBW:
- sflags = "GCS_VERBW"; break;
+ sflags = L"GCS_VERBW"; break;
case GCS_VERBA:
- sflags = "GCS_VERBA"; break;
+ sflags = L"GCS_VERBA"; break;
}

- TDEBUG_TRACE(
- "CShellExtCMenu::GetCommandString: idCmd = " << idCmd
- << ", uFlags = " << uFlags << " (" << sflags << ")"
- << ", cchMax = " << cchMax
+ TDEBUG_TRACEW(
+ L"CShellExtCMenu::GetCommandString: idCmd = " << idCmd
+ << L", uFlags = " << uFlags << L" (" << sflags << L")"
+ << L", cchMax = " << cchMax
);

MenuIdCmdMap::iterator iter = myMenuIdMap.find(static_cast<UINT>(idCmd));
if (iter == myMenuIdMap.end())
{
- TDEBUG_TRACE("***** CShellExtCMenu::GetCommandString: idCmd not found");
+ TDEBUG_TRACEW(L"***** CShellExtCMenu::GetCommandString: idCmd not found");
}
else
{
- TDEBUG_TRACE(
- "CShellExtCMenu::GetCommandString: name = \"" << iter->second.name << "\"");
+ TDEBUG_TRACEW(
+ L"CShellExtCMenu::GetCommandString: name = \"" << iter->second.name << L"\"");

if (uFlags == GCS_HELPTEXTW)
{
@@ -643,10 +707,10 @@ CShellExtCMenu::GetCommandString(
size_t size = iter->second.helpText.size();
if (size >= 40)
{
- TDEBUG_TRACE(
- "***** CShellExtCMenu::GetCommandString: warning:"
- << " length of help text is " << size
- << ", which is not reasonably short (<40)");
+ TDEBUG_TRACEW(
+ L"***** CShellExtCMenu::GetCommandString: warning:"
+ << L" length of help text is " << size
+ << L", which is not reasonably short (<40)");
}
}
else if (uFlags == GCS_HELPTEXTA)
@@ -673,7 +737,7 @@ CShellExtCMenu::GetCommandString(

if (cchMax < 1)
{
- TDEBUG_TRACE("CShellExtCMenu::GetCommandString: cchMax = "
+ TDEBUG_TRACEW(L"CShellExtCMenu::GetCommandString: cchMax = "
<< cchMax << " (is <1)");
return res;
}
@@ -683,7 +747,8 @@ CShellExtCMenu::GetCommandString(
if (uFlags & GCS_UNICODE)
{
wchar_t* const dest = reinterpret_cast<wchar_t*>(pszName);
- const wchar_t* const src = pszw ? pszw : _WCSTR(psz);
+ std::wstring ws_src = MultibyteToWide(psz, CP_ACP, 0) ;
+ const wchar_t* const src = pszw ? pszw : ws_src.c_str();

wcsncpy(dest, src, cchMax-1);
*(dest + cchMax-1) = 0;
@@ -700,15 +765,15 @@ CShellExtCMenu::GetCommandString(

size = strlen(psz);

- TDEBUG_TRACE("CShellExtCMenu::GetCommandString: res = " << int(res)
+ TDEBUG_TRACEW(L"CShellExtCMenu::GetCommandString: res = " << int(res)
<< ", pszName = \"" << psz << "\"");
}

if (size > cchMax-1)
{
- TDEBUG_TRACE(
- "***** CShellExtCMenu::GetCommandString: string was truncated: size = "
- << size << ", cchMax = " << cchMax);
+ TDEBUG_TRACEW(
+ L"***** CShellExtCMenu::GetCommandString: string was truncated: size = "
+ << size << L", cchMax = " << cchMax);
}

return res;
@@ -774,33 +839,43 @@ CShellExtCMenu::HandleMenuMsg2(
}


-void CShellExtCMenu::RunDialog(const std::string &cmd)
+void CShellExtCMenu::RunDialog(const std::wstring &cmd)
{
- std::string dir = GetTHgProgRoot();
+ bool support_listfile_utf8 = false ;
+ std::wstring dir = GetTHgProgRoot();
if (dir.empty())
{
- TDEBUG_TRACE("RunDialog: THG root is empty");
+ TDEBUG_TRACEW(L"RunDialog: THG root is empty");
return;
}
- std::string hgcmd = dir + "\\thgw.exe";

- WIN32_FIND_DATAA data;
- HANDLE hfind = FindFirstFileA(hgcmd.c_str(), &data);
+ std::wstring hgcmd ;
+ hgcmd = dir + L"\\" + THG_FILENAME + L".exe";
+
+ WIN32_FIND_DATA data;
+ HANDLE hfind = FindFirstFile(hgcmd.c_str(), &data);
if (hfind == INVALID_HANDLE_VALUE)
{
- hgcmd = dir + "\\hgtk.exe";
- hfind = FindFirstFileA(hgcmd.c_str(), &data);
+ hgcmd = dir + L"\\" + HGTK_FILENAME + L".exe";
+ hfind = FindFirstFile(hgcmd.c_str(), &data);
if (hfind == INVALID_HANDLE_VALUE)
- hgcmd = dir + "\\thg.cmd";
+ {
+ support_listfile_utf8 = true ;
+ hgcmd = dir + L"\\" + THG_FILENAME + L".cmd";
+ }
else
+ {
FindClose(hfind);
+ support_listfile_utf8 = false ;
+ }
}
else
+ {
FindClose(hfind);
+ support_listfile_utf8 = true ;
+ }

- hgcmd = Quote(hgcmd) + " --nofork " + cmd;
-
- std::string cwd;
+ std::wstring cwd;
if (!myFolder.empty())
{
cwd = myFolder;
@@ -811,88 +886,115 @@ void CShellExtCMenu::RunDialog(const std
}
else
{
- TDEBUG_TRACE("***** RunDialog: can't get cwd");
+ TDEBUG_TRACEW(L"***** RunDialog: can't get cwd");
return;
}

- if (cmd == "thgstatus")
+ if (cmd == L"thgstatus")
{
if (Thgstatus::remove(cwd) != 0)
{
- std::string p = dir + "\\TortoiseHgOverlayServer.exe";
+ std::wstring p = dir + L"\\TortoiseHgOverlayServer.exe";
LaunchCommand(Quote(p), dir);
}
InitStatus::check();
return;
}

+ hgcmd = Quote(hgcmd) + L" --nofork " + cmd;
+
+ UINT CodePage = LISTFILE_CP_ACP ;
+ std::wstring listfile_opt ;
+ if ( support_listfile_utf8 )
+ {
+ CodePage = LISTFILE_CP_UTF8 ;
+ listfile_opt = LISTFILE_OPT_UTF8 ;
+ }
+ else
+ {
+ CodePage = LISTFILE_CP_ACP ;
+ listfile_opt = LISTFILE_OPT_ACP ;
+ }
+
if (!myFiles.empty())
{
- const std::string tempfile = GetTemporaryFile();
+ const std::wstring tempfile = GetTemporaryFile();
+
if (tempfile.empty())
{
- TDEBUG_TRACE("***** RunDialog: error: GetTemporaryFile returned empty string");
+ TDEBUG_TRACEW(L"***** RunDialog: error: GetTemporaryFile returned empty string");
return;
}

- TDEBUG_TRACE("RunDialog: temp file = " << tempfile);
- HANDLE tempfileHandle = CreateFileA(
+ TDEBUG_TRACEW(L"RunDialog: temp file = " << tempfile);
+ HANDLE tempfileHandle = CreateFile(
tempfile.c_str(), GENERIC_WRITE,
FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
);

if (tempfileHandle == INVALID_HANDLE_VALUE)
{
- TDEBUG_TRACE("***** RunDialog: error: failed to create file " << tempfile);
+ TDEBUG_TRACEW(L"***** RunDialog: error: failed to create file " << tempfile);
return;
}

- typedef std::vector<std::string>::size_type ST;
+ typedef std::vector<std::wstring>::size_type ST;
for (ST i = 0; i < myFiles.size(); i++)
{
DWORD dwWritten;
- TDEBUG_TRACE("RunDialog: temp file adding " << myFiles[i]);
+ std::string str_file = WideToMultibyte(myFiles[i], CodePage);
+ TDEBUG_TRACEW(L"RunDialog: temp file adding " << myFiles[i]);
WriteFile(
- tempfileHandle, myFiles[i].c_str(),
- static_cast<DWORD>(myFiles[i].size()), &dwWritten, 0
+ tempfileHandle, str_file.c_str(),
+ static_cast<DWORD>(str_file.size()), &dwWritten, 0
);
- WriteFile(tempfileHandle, "\n", 1, &dwWritten, 0);
+ WriteFile(tempfileHandle, "\n", sizeof(char), &dwWritten, 0);
}
CloseHandle(tempfileHandle);
- hgcmd += " --listfile " + Quote(tempfile);
+ hgcmd += listfile_opt + Quote(tempfile);
}

- LaunchCommand(hgcmd, cwd);
+ std::wstring run_dir ;
+ std::wstring root = GetHgRepoRoot(cwd);
+ if ( ! root.empty() )
+ {
+ run_dir = root ;
+ }
+ else
+ {
+ run_dir = cwd ;
+ }
+ LaunchCommand(hgcmd, run_dir);
InitStatus::check();
}

void CShellExtCMenu::PrintDebugHeader(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj)
{
- TDEBUG_TRACE("CShellExtCMenu::Initialize");
+ TDEBUG_TRACEW(L"CShellExtCMenu::Initialize");

// get installed MSI product id (for debugging purposes for now)
#ifdef _M_X64
- const char* shellexid = "{D5D1E532-CDAD-4FFD-9695-757B8A29B4BA}";
+ const wchar_t* shellexid = L"{D5D1E532-CDAD-4FFD-9695-757B8A29B4BA}";
#else
- const char* shellexid = "{728E8840-5878-4EA7-918F-281C2697ABB1}";
+ const wchar_t* shellexid = L"{728E8840-5878-4EA7-918F-281C2697ABB1}";
#endif
- std::vector<char> product_id(50, 0);
- UINT msires = ::MsiGetProductCodeA(shellexid, &product_id[0]);
- TDEBUG_TRACE("MSI shellexid: " << shellexid);
- TDEBUG_TRACE("MSI msires: " << msires);
- TDEBUG_TRACE("MSI installed product id: " << &product_id[0]);
+ std::vector<wchar_t> product_id(50, 0);
+ UINT msires = ::MsiGetProductCode(shellexid, &product_id[0]);
+ TDEBUG_TRACEW(L"MSI shellexid: " << shellexid);
+ TDEBUG_TRACEW(L"MSI msires: " << msires);
+ TDEBUG_TRACEW(L"MSI installed product id: " << &product_id[0]);

DWORD busize = 300;
- std::vector<char> buf(busize, 0);
- msires = ::MsiGetProductInfoA(
+ std::vector<wchar_t> buf(busize, 0);
+ msires = ::MsiGetProductInfoW(
&product_id[0], INSTALLPROPERTY_INSTALLLOCATION, &buf[0], &busize);
if (msires == ERROR_SUCCESS)
{
- TDEBUG_TRACE("MSI install location: " << &buf[0]);
+ TDEBUG_TRACEW(L"MSI install location: " << &buf[0]);
}
else
{
- TDEBUG_TRACE("MSI install location: error " << msires);
+ TDEBUG_TRACEW(L"MSI install location: error " << msires);
}

TDEBUG_TRACEW(
@@ -900,8 +1002,8 @@ void CShellExtCMenu::PrintDebugHeader(LP
<< ThgVersion::get() << L"----"
);

- TDEBUG_TRACE(" pIDFolder: " << pIDFolder);
- TDEBUG_TRACE(" pDataObj: " << pDataObj);
+ TDEBUG_TRACEW(L" pIDFolder: " << pIDFolder);
+ TDEBUG_TRACEW(L" pDataObj: " << pDataObj);
}

STDMETHODIMP CShellExtCMenu::Initialize(
@@ -918,56 +1020,54 @@ STDMETHODIMP CShellExtCMenu::Initialize(
{
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
- if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)) && stg.hGlobal)
+ if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)))
{
HDROP hDrop = (HDROP) GlobalLock(stg.hGlobal);

if (hDrop)
{
UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
- TDEBUG_TRACE(" hDrop uNumFiles = " << uNumFiles);
+ TDEBUG_TRACEW(L" hDrop uNumFiles = " << uNumFiles);
for (UINT i = 0; i < uNumFiles; ++i) {
if (DragQueryFile(hDrop, i, name, MAX_PATH) > 0)
{
- TDEBUG_TRACE(" DragQueryFile [" << i << "] = " << name);
+ TDEBUG_TRACEW(L" DragQueryFile [" << i << "] = " << name);
myFiles.push_back(name);
}
}
}
- else
- {
- TDEBUG_TRACE(" hDrop is NULL ");
- }

GlobalUnlock(stg.hGlobal);
- if (stg.pUnkForRelease)
+ ReleaseStgMedium(&stg);
+
+ if (hDrop == NULL)
{
- IUnknown* relInterface = (IUnknown*) stg.pUnkForRelease;
- relInterface->Release();
+ TDEBUG_TRACEW(L" hDrop is NULL ");
+ return E_INVALIDARG;
}
}
else
{
- TDEBUG_TRACE(" pDataObj->GetData failed");
+ TDEBUG_TRACEW(L" pDataObj->GetData failed");
+ return E_INVALIDARG;
}
}

// if a directory background
if (pIDFolder)
{
- SHGetPathFromIDList(pIDFolder, name);
- TDEBUG_TRACE(" Folder " << name);
- myFolder = name;
+ if (SHGetPathFromIDList(pIDFolder, name) == TRUE)
+ {
+ TDEBUG_TRACEW(L" Folder " << name);
+ myFolder = name;
+ }
+ else
+ {
+ TDEBUG_TRACEW(L" SHGetPathFromIDList() failed");
+ return E_INVALIDARG;
+ }
}
-
- // disable context menu if neither the folder nor the files
- // have been found
- if (myFolder.empty() && myFiles.empty()) {
- TDEBUG_TRACE(" shell extension not available on this object");
- return E_FAIL;
- } else {
- return S_OK;
- }
+ return S_OK;
}


diff --git a/win32/shellext/CShellExtCMenu.h b/win32/shellext/CShellExtCMenu.h
--- a/win32/shellext/CShellExtCMenu.h
+++ b/win32/shellext/CShellExtCMenu.h
@@ -9,14 +9,14 @@

struct MenuDescription
{
- std::string name;
+ std::wstring name;
std::wstring menuText;
std::wstring helpText;
- std::string iconName;
+ std::wstring iconName;
UINT idCmd;
};

-typedef std::map<std::string, MenuDescription> MenuDescriptionMap;
+typedef std::map<std::wstring, MenuDescription> MenuDescriptionMap;

typedef std::map<UINT, MenuDescription> MenuIdCmdMap;

@@ -25,21 +25,21 @@ class CShellExtCMenu: public CSimpleUnkn
{

protected:
- ULONG m_cRef;
- std::vector<std::string> myFiles;
- std::string myFolder;
- MenuDescriptionMap myDescMap;
- MenuIdCmdMap myMenuIdMap;
+ ULONG m_cRef;
+ std::vector<std::wstring> myFiles;
+ std::wstring myFolder;
+ MenuDescriptionMap myDescMap;
+ MenuIdCmdMap myMenuIdMap;

- virtual void RunDialog(const std::string&);
+ virtual void RunDialog(const std::wstring&);

void TweakMenuForVista(HMENU menu);
void PrintDebugHeader(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj);
void InitMenuMaps(const MenuDescription *menuDescs, std::size_t sz);
void InsertMenuItemByName(
- HMENU hMenu, const std::string& name, UINT indexMenu,
- UINT idCmd, UINT idCmdFirst, const std::wstring& prefix);
- void AddMenuList(UINT idCmd, const std::string& name);
+ HMENU hMenu, const std::wstring& name, UINT indexMenu,
+ UINT idCmd, UINT idCmdFirst, const std::wstring& prefix);
+ void AddMenuList(UINT idCmd, const std::wstring& name);

public:
explicit CShellExtCMenu(const char dummy);
diff --git a/win32/shellext/CShellExtDnd.cpp b/win32/shellext/CShellExtDnd.cpp
--- a/win32/shellext/CShellExtDnd.cpp
+++ b/win32/shellext/CShellExtDnd.cpp
@@ -9,19 +9,19 @@

static const MenuDescription CDndMenuDescList[] =
{
- {"drag_move", L"Hg Move versioned item(s) here",
- L"", "hg.ico", 0},
- {"drag_copy", L"Hg Copy versioned item(s) here",
- L"", "hg.ico", 0},
+ {L"drag_move", L"Hg Move versioned item(s) here",
+ L"", L"hg.ico", 0},
+ {L"drag_copy", L"Hg Copy versioned item(s) here",
+ L"", L"hg.ico", 0},
/* Add new items here */

// template
- //{"", L"", L"", ".ico", 0},
+ //{L"", L"", L"", ".ico", 0},
};


-static const char* const DropMenu =
- "drag_move drag_copy"
+static const wchar_t* const DropMenu =
+ L"drag_move drag_copy"
;


@@ -32,7 +32,7 @@ STDMETHODIMP
CShellExtDnd::QueryContextMenu(
HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
- TDEBUG_TRACE("CShellExtDnd::QueryContextMenu");
+ TDEBUG_TRACEW(L"CShellExtDnd::QueryContextMenu");

if ((uFlags & CMF_DEFAULTONLY)!=0)
return S_OK; //we don't change the default action
@@ -45,16 +45,16 @@ CShellExtDnd::QueryContextMenu(

InitMenuMaps(CDndMenuDescList, sizeof(CDndMenuDescList) / sizeof(MenuDescription));

- typedef std::vector<std::string> entriesT;
- typedef entriesT::const_iterator entriesIter;
+ typedef std::vector<std::wstring> entriesT;
+ typedef entriesT::const_iterator entriesIter;

- const char* entries_string = DropMenu;
+ const wchar_t* entries_string = DropMenu;
entriesT entries;
- Tokenize(entries_string, entries, " ");
+ Tokenize(entries_string, entries, L" ");

for (entriesIter i = entries.begin(); i != entries.end(); i++)
{
- std::string name = *i;
+ std::wstring name = *i;
InsertMenuItemByName(
hMenu, name, indexMenu++,
idCmd++, idCmdFirst, L""
@@ -71,10 +71,10 @@ CShellExtDnd::QueryContextMenu(
}


-void CShellExtDnd::RunDialog(const std::string &cmd)
+void CShellExtDnd::RunDialog(const std::wstring &cmd)
{
- if (cmd == "drag_move" || cmd == "drag_copy") {
- //Append the current directory as the dest
+ if (cmd == L"drag_move" || cmd == L"drag_copy") {
+ //Append the current directory as the dest
myFiles.push_back(myFolder);
}
CShellExtCMenu::RunDialog(cmd);
@@ -95,16 +95,16 @@ STDMETHODIMP CShellExtDnd::Initialize(
if (pIDFolder)
{
SHGetPathFromIDList(pIDFolder, name);
- TDEBUG_TRACE(" Folder " << name);
+ TDEBUG_TRACEW(L" Folder " << name);
myFolder = name;
}

- std::string root;
+ std::wstring root;

//short circuit if we're dragging into a non-Hg repository
if (myFolder.empty() || (root = GetHgRepoRoot(myFolder)).empty())
{
- TDEBUG_TRACE(" drag into a non-Hg repos directory");
+ TDEBUG_TRACEW(L" drag into a non-Hg repos directory");
return E_FAIL;
}

@@ -119,24 +119,24 @@ STDMETHODIMP CShellExtDnd::Initialize(
if (hDrop)
{
UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
- TDEBUG_TRACE(" hDrop uNumFiles = " << uNumFiles);
+ TDEBUG_TRACEW(L" hDrop uNumFiles = " << uNumFiles);
for (UINT i = 0; i < uNumFiles; ++i) {
if (DragQueryFile(hDrop, i, name, MAX_PATH) > 0)
{
- TDEBUG_TRACE(" DragQueryFile [" << i << "] = " << name);
+ TDEBUG_TRACEW(L" DragQueryFile [" << i << L"] = " << name);
if (GetHgRepoRoot(name) != root)
{
- TDEBUG_TRACE(" " << name << " isn't in target dir repository");
+ TDEBUG_TRACEW(L" " << name << L" isn't in target dir repository");
myFiles.clear();
break;
- }
+ }
myFiles.push_back(name);
}
}
}
else
{
- TDEBUG_TRACE(" hDrop is NULL ");
+ TDEBUG_TRACEW(L" hDrop is NULL ");
}

GlobalUnlock(stg.hGlobal);
@@ -148,14 +148,14 @@ STDMETHODIMP CShellExtDnd::Initialize(
}
else
{
- TDEBUG_TRACE(" pDataObj->GetData failed");
+ TDEBUG_TRACEW(L" pDataObj->GetData failed");
}
}

// disable context menu if neither the folder nor the files
// have been found
if (myFiles.empty()) {
- TDEBUG_TRACE(" shell extension not available on this object");
+ TDEBUG_TRACEW(L" shell extension not available on this object");
return E_FAIL;
} else {
return S_OK;
@@ -163,7 +163,7 @@ STDMETHODIMP CShellExtDnd::Initialize(
}


-CShellExtDnd::CShellExtDnd(const char dummy) :
+CShellExtDnd::CShellExtDnd(const wchar_t dummy) :
CShellExtCMenu(dummy)
{
}
diff --git a/win32/shellext/CShellExtDnd.h b/win32/shellext/CShellExtDnd.h
--- a/win32/shellext/CShellExtDnd.h
+++ b/win32/shellext/CShellExtDnd.h
@@ -9,10 +9,10 @@ class CShellExtDnd: public CShellExtCMen
{

protected:
- virtual void RunDialog(const std::string&);
+ virtual void RunDialog(const std::wstring&);

public:
- explicit CShellExtDnd(const char dummy);
+ explicit CShellExtDnd(const wchar_t dummy);
~CShellExtDnd();

// IContextMenu3
diff --git a/win32/shellext/CShellExtOverlay.cpp b/win32/shellext/CShellExtOverlay.cpp
--- a/win32/shellext/CShellExtOverlay.cpp
+++ b/win32/shellext/CShellExtOverlay.cpp
@@ -12,7 +12,7 @@
STDMETHODIMP CShellExtOverlay::GetOverlayInfo(
LPWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags)
{
- TDEBUG_TRACE("CShellExtOverlay::GetOverlayInfo: myTortoiseClass = " << myTortoiseClass);
+ TDEBUG_TRACEW(L"CShellExtOverlay::GetOverlayInfo: myTortoiseClass = " << myTortoiseClass);
// icons are determined by TortoiseOverlays shim
*pIndex = 0;
*pdwFlags = 0;
@@ -32,8 +32,8 @@ STDMETHODIMP CShellExtOverlay::IsMemberO
{
ThgCriticalSection cs(CShellExt::GetCriticalSection());

- std::string cval;
- if (GetRegistryConfig("EnableOverlays", cval) != 0 && cval == "0")
+ std::wstring cval;
+ if (GetRegistryConfig(L"EnableOverlays", cval) != 0 && cval == L"0")
return S_FALSE;

// This overlay handler processes all filenames in lowercase, so that a path
@@ -43,23 +43,23 @@ STDMETHODIMP CShellExtOverlay::IsMemberO
std::wstring lowerpath(pwszPath);
::CharLowerW(const_cast<wchar_t*>(lowerpath.c_str()));

- std::string path = WideToMultibyte(lowerpath.c_str());
+ std::wstring path = lowerpath; //WideToMultibyte(lowerpath.c_str());

- if (GetRegistryConfig("LocalDisksOnly", cval) != 0 && cval != "0")
+ if (GetRegistryConfig(L"LocalDisksOnly", cval) != 0 && cval != L"0")
{
if (::PathIsNetworkPath(path.c_str()))
return S_FALSE;

if (path.size() > 2 && path[1] == ':')
{
- std::string t = "C:\\";
+ std::wstring t = L"C:\\";
t[0] = path[0];
- if (::GetDriveType(t.c_str()) == 4)
+ if (::GetDriveTypeW(t.c_str()) == 4)
return S_FALSE;
}
}

- char filterStatus = 0;
+ wchar_t filterStatus = 0;
if (myTortoiseClass == 'A')
filterStatus = 'A';

@@ -87,4 +87,4 @@ CShellExtOverlay::~CShellExtOverlay()
CShellExt::DecDllRef();
}

-IMPLEMENT_UNKNOWN(CShellExtOverlay)
\ No newline at end of file
+IMPLEMENT_UNKNOWN(CShellExtOverlay)
diff --git a/win32/shellext/Directory.cpp b/win32/shellext/Directory.cpp
--- a/win32/shellext/Directory.cpp
+++ b/win32/shellext/Directory.cpp
@@ -15,16 +15,16 @@
// 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 <time.h>

-#include "stdafx.h"
-
#include "Directory.h"
#include "Winstat.h"


Directory::Directory(
- Directory* p, const std::string& n, const std::string& basepath
+ Directory* p, const std::wstring& n, const std::wstring& basepath
):
parent_(p), name_(n)
{
@@ -33,7 +33,7 @@ Directory::Directory(
else if (basepath.empty())
path_ = n;
else
- path_ = basepath + '/' + n;
+ path_ = basepath + L'/' + n;
}


@@ -46,13 +46,13 @@ Directory::~Directory()
}


-int splitbase(const std::string& n, std::string& base, std::string& rest)
+int splitbase(const std::wstring& n, std::wstring& base, std::wstring& rest)
{
if (n.empty())
return 0;

- size_t x = n.find_first_of ('/');
- if (x == std::string::npos)
+ size_t x = n.find_first_of (L'/');
+ if (x == std::wstring::npos)
{
base.clear();
rest = n;
@@ -69,19 +69,19 @@ int splitbase(const std::string& n, std:
}


-int Directory::add(const std::string& n_in, Direntry& e)
+int Directory::add(const std::wstring& n_in, Direntry& e)
{
- std::string base;
- std::string rest;
+ std::wstring base;
+ std::wstring rest;

- std::string n = n_in;
+ std::wstring n = n_in;
Directory* cur = this;

for (;;)
{

if (!splitbase(n, base, rest)) {
- TDEBUG_TRACE("Directory(" << path() << ")::add(" << n_in
+ TDEBUG_TRACEW(L"Directory(" << path() << ")::add(" << n_in
<< "): splitbase returned 0");
return 0;
}
@@ -115,12 +115,12 @@ int Directory::add(const std::string& n_
}


-const Direntry* Directory::get(const std::string& n_in) const
+const Direntry* Directory::get(const std::wstring& n_in) const
{
- std::string base;
- std::string rest;
+ std::wstring base;
+ std::wstring rest;

- std::string n = n_in;
+ std::wstring n = n_in;
const Directory* cur = this;

for (;;)
@@ -129,7 +129,7 @@ const Direntry* Directory::get(const std

if (!splitbase(n, base, rest))
{
- TDEBUG_TRACE("Directory(" << path() << ")::get("
+ TDEBUG_TRACEW(L"Directory(" << path() << ")::get("
<< n_in << "): splitbase returned 0");
return 0;
}
@@ -161,12 +161,12 @@ const Direntry* Directory::get(const std
}


-Directory* Directory::getdir(const std::string& n_in)
+Directory* Directory::getdir(const std::wstring& n_in)
{
- std::string base;
- std::string rest;
+ std::wstring base;
+ std::wstring rest;

- std::string n = n_in;
+ std::wstring n = n_in;
const Directory* cur = this;

for (;;)
@@ -175,13 +175,13 @@ Directory* Directory::getdir(const std::

if (!splitbase(n, base, rest))
{
- TDEBUG_TRACE("Directory(" << path() << ")::getdir("
+ TDEBUG_TRACEW(L"Directory(" << path() << ")::getdir("
<< n_in << "): splitbase returned 0");
return 0;
}

const bool leaf = base.empty();
- const std::string& searchstr = (leaf ? n : base);
+ const std::wstring& searchstr = (leaf ? n : base);

for (DirsT::const_iterator i = cur->subdirs_.begin();
i != cur->subdirs_.end(); ++i)
@@ -208,32 +208,32 @@ void Directory::print() const
const Directory* d = *i;
if (!d)
{
- TDEBUG_TRACE("Directory(" << path() << ")::print: error: d is 0");
+ TDEBUG_TRACEW(L"Directory(" << path() << ")::print: error: d is 0");
return;
}
d->print();
}

- std::string base = path();
+ std::wstring base = path();

time_t t;
- std::string s;
- char* ctime_res = 0;
+ std::wstring s;
+ wchar_t* ctime_res = 0;

for (FilesT::const_iterator i = files_.begin(); i != files_.end(); ++i)
{
- std::string p = (!base.empty() ? base + "/" + i->name : i->name);
+ std::wstring p = (!base.empty() ? base + L"/" + i->name : i->name);
t = i->mtime;
- ctime_res = ctime(&t);
+ ctime_res = _wctime(&t);
if (ctime_res) {
s = ctime_res;
s.resize(s.size() - 1); // strip ending '\n'
}
else {
- s = "unset";
+ s = L"unset";
}
- printf(
- "%c %6o %10u %-24s %s\n",
+ wprintf(
+ L"%c %6o %10u %-24s %s\n",
i->state, i->mode, i->size, s.c_str(), p.c_str()
);
}
diff --git a/win32/shellext/Directory.h b/win32/shellext/Directory.h
--- a/win32/shellext/Directory.h
+++ b/win32/shellext/Directory.h
@@ -30,22 +30,22 @@ class Directory
typedef std::vector<Direntry> FilesT;

Directory* const parent_;
- const std::string name_;
- std::string path_;
+ const std::wstring name_;
+ std::wstring path_;

DirsT subdirs_;
FilesT files_;

public:
- Directory(Directory* p, const std::string& n, const std::string& basepath);
+ Directory(Directory* p, const std::wstring& n, const std::wstring& basepath);
~Directory();

- const std::string& path() const { return path_; }
+ const std::wstring& path() const { return path_; }

- int add(const std::string& relpath, Direntry& e);
+ int add(const std::wstring& relpath, Direntry& e);

- const Direntry* get(const std::string& relpath) const;
- Directory* getdir(const std::string& n);
+ const Direntry* get(const std::wstring& relpath) const;
+ Directory* getdir(const std::wstring& n);

void print() const;
};
diff --git a/win32/shellext/DirectoryStatus.cpp b/win32/shellext/DirectoryStatus.cpp
--- a/win32/shellext/DirectoryStatus.cpp
+++ b/win32/shellext/DirectoryStatus.cpp
@@ -19,15 +19,15 @@
#include "DirectoryStatus.h"
#include "Thgstatus.h"
#include "TortoiseUtils.h"
+#include "StringUtils.h"

-
-char DirectoryStatus::status(const std::string& relpath_) const
+char DirectoryStatus::status(const std::wstring& relpath_) const
{
char res = 'C';
bool added = false;
bool modified = false;

- const std::string relpath = relpath_ + '/';
+ const std::wstring relpath = relpath_ + L'/';

for (V::const_iterator i = v_.begin(); i != v_.end(); ++i)
{
@@ -56,18 +56,26 @@ char DirectoryStatus::status(const std::
}


-int DirectoryStatus::read(const std::string& hgroot, const std::string& cwd)
+int DirectoryStatus::read(
+ const std::wstring& hgroot,
+ const std::wstring& cwd
+ )
{
+ TDEBUG_TRACEW(
+ L"DirectoryStatus::read: hgroot: '" << hgroot << L"'"
+ << L" cwd: '" << L"'"
+ );
+
v_.clear();
noicons_ = false;

- std::string p = hgroot + "\\.hg\\thgstatus";
+ std::wstring p = hgroot + L"\\.hg\\thgstatus";

FILE *f = fopenReadRenameAllowed(p.c_str());
if (!f)
{
- TDEBUG_TRACE("DirectoryStatus::read: can't open '" << p << "'");
- std::string p = (cwd.size() < hgroot.size() ? hgroot : cwd);
+ TDEBUG_TRACEW(L"DirectoryStatus::read: can't open '" << p << L"'");
+ std::wstring p = (cwd.size() < hgroot.size() ? hgroot : cwd);
Thgstatus::update(p);
return 0;
}
@@ -112,23 +120,23 @@ int DirectoryStatus::read(const std::str

e.status_ = line[0];

- std::string path;
+ std::string path;
+ std::wstring wpath;
if (line.size() > 1)
{
path = line.c_str() + 1;
- ::CharLower(const_cast<char*>(path.c_str()));
+ wpath = ThgMultibyteToWide(path);
+ ::CharLower(const_cast<wchar_t*>(wpath.c_str()));
}
- path.push_back('/');
-
- e.path_ = path;
-
+ wpath.push_back(L'/');
+ e.path_ = wpath;
v_.push_back(e);
}

close:
fclose(f);

- TDEBUG_TRACE("DirectoryStatus::read(" << hgroot << "): done. "
+ TDEBUG_TRACEW(L"DirectoryStatus::read(" << hgroot << "): done. "
<< v_.size() << " entries read. noicons_ = " << noicons_ );

return res;
@@ -137,7 +145,7 @@ close:

struct CacheEntry
{
- std::string hgroot_;
+ std::wstring hgroot_;
DirectoryStatus ds_;
bool readfailed_;
unsigned tickcount_;
@@ -147,10 +155,11 @@ struct CacheEntry


DirectoryStatus* DirectoryStatus::get(
- const std::string& hgroot, const std::string& cwd)
+ const std::wstring& hgroot,
+ const std::wstring& cwd
+ )
{
static CacheEntry ce;
-
unsigned tc = GetTickCount();

if (ce.hgroot_ != hgroot || (tc - ce.tickcount_) > 2000)
@@ -163,5 +172,3 @@ DirectoryStatus* DirectoryStatus::get(

return (ce.readfailed_ ? 0 : &ce.ds_);
}
-
-
diff --git a/win32/shellext/DirectoryStatus.h b/win32/shellext/DirectoryStatus.h
--- a/win32/shellext/DirectoryStatus.h
+++ b/win32/shellext/DirectoryStatus.h
@@ -22,7 +22,7 @@ class DirectoryStatus
{
struct E
{
- std::string path_;
+ std::wstring path_;
char status_;

E(): status_(0) {}
@@ -36,10 +36,15 @@ public:
DirectoryStatus(): noicons_(false) {}

static DirectoryStatus* get(
- const std::string& hgroot, const std::string& cwd);
- char status(const std::string& relpath) const;
+ const std::wstring& hgroot,
+ const std::wstring& cwd
+ );
+ char status(const std::wstring& relpath) const;
bool noicons() const { return noicons_; }

private:
- int read(const std::string& hgroot, const std::string& cwd);
+ int read(
+ const std::wstring& hgroot,
+ const std::wstring& cwd
+ );
};
diff --git a/win32/shellext/Direntry.cpp b/win32/shellext/Direntry.cpp
--- a/win32/shellext/Direntry.cpp
+++ b/win32/shellext/Direntry.cpp
@@ -42,8 +42,6 @@ int Direntry::read(FILE* f, std::vector<
fread(&relpath[0], sizeof(char), length, f);
relpath[length] = 0;

- ::CharLowerBuff(&relpath[0], length);
-
return 1;
}

diff --git a/win32/shellext/Direntry.h b/win32/shellext/Direntry.h
--- a/win32/shellext/Direntry.h
+++ b/win32/shellext/Direntry.h
@@ -35,7 +35,7 @@ public:
unsigned size;
unsigned mtime;

- std::string name;
+ std::wstring name;

int read(FILE* f, std::vector<char>& relpath);
char status(const Winstat& stat) const;
diff --git a/win32/shellext/Dirstatecache.cpp b/win32/shellext/Dirstatecache.cpp
--- a/win32/shellext/Dirstatecache.cpp
+++ b/win32/shellext/Dirstatecache.cpp
@@ -31,7 +31,10 @@ std::list<Dirstatecache::E>& Dirstatecac


Dirstate* Dirstatecache::get(
- const std::string& hgroot, const std::string& cwd, bool& unset)
+ const std::wstring& hgroot,
+ const std::wstring& cwd,
+ bool& unset
+ )
{
unset = false;

@@ -45,7 +48,7 @@ Dirstate* Dirstatecache::get(
}

Winstat64 stat;
- std::string path = hgroot + "\\.hg\\dirstate";
+ std::wstring path = hgroot + L"\\.hg\\dirstate";

unsigned tc = GetTickCount();
bool new_stat = false;
@@ -54,15 +57,15 @@ Dirstate* Dirstatecache::get(
{
if (stat.lstat(path.c_str()) != 0)
{
- TDEBUG_TRACE("Dirstatecache::get: lstat(" << path <<") failed");
+ TDEBUG_TRACEW(L"Dirstatecache::get: lstat(" << path <<") failed");
return 0;
}
- TDEBUG_TRACE("Dirstatecache::get: lstat(" << path <<") ok ");
+ TDEBUG_TRACEW(L"Dirstatecache::get: lstat(" << path <<") ok ");
new_stat = true;

if (cache().size() >= 10)
{
- TDEBUG_TRACE("Dirstatecache::get: dropping "
+ TDEBUG_TRACEW(L"Dirstatecache::get: dropping "
<< cache().back().hgroot);
delete cache().back().dstate;
cache().back().dstate = 0;
@@ -80,36 +83,36 @@ Dirstate* Dirstatecache::get(
{
if (0 != stat.lstat(path.c_str()))
{
- TDEBUG_TRACE("Dirstatecache::get: lstat(" << path <<") failed");
- TDEBUG_TRACE("Dirstatecache::get: dropping " << iter->hgroot);
+ TDEBUG_TRACEW(L"Dirstatecache::get: lstat(" << path <<") failed");
+ TDEBUG_TRACEW(L"Dirstatecache::get: dropping " << iter->hgroot);
delete iter->dstate;
iter->dstate = 0;
cache().erase(iter);
return 0;
}
iter->tickcount = tc;
- TDEBUG_TRACE("Dirstatecache::get: lstat(" << path <<") ok ");
+ TDEBUG_TRACEW(L"Dirstatecache::get: lstat(" << path <<") ok ");
new_stat = true;
}

- if (iter->dstate)
+ if (iter->dstate)
{
unset = iter->unset;
-
if (!new_stat)
+ {
return iter->dstate;
-
+ }
if (iter->dstate_mtime == stat.mtime
&& iter->dstate_size == stat.size)
{
return iter->dstate;
}

- TDEBUG_TRACE("Dirstatecache::get: refreshing " << hgroot);
- }
- else
+ TDEBUG_TRACEW(L"Dirstatecache::get: refreshing " << hgroot);
+ }
+ else
{
- TDEBUG_TRACE("Dirstatecache::get: reading " << hgroot);
+ TDEBUG_TRACEW(L"Dirstatecache::get: reading " << hgroot);
}

unset = false;
@@ -123,13 +126,13 @@ Dirstate* Dirstatecache::get(
{
if (iter->unset)
{
- TDEBUG_TRACE(
- "Dirstatecache::get: **** old and new have unset entries");
+ TDEBUG_TRACEW(
+ L"Dirstatecache::get: **** old and new have unset entries");
request_thgstatus_update = false;
}
else
{
- TDEBUG_TRACE("Dirstatecache::get: new has unset entries");
+ TDEBUG_TRACEW(L"Dirstatecache::get: new has unset entries");
}
}

@@ -139,7 +142,7 @@ Dirstate* Dirstatecache::get(
iter->dstate = ds.release();

unsigned delta = tc1 - tc0;
- TDEBUG_TRACE("Dirstatecache::get: read done in " << delta << " ticks, "
+ TDEBUG_TRACEW(L"Dirstatecache::get: read done in " << delta << " ticks, "
<< cache().size() << " repos in cache");

iter->dstate_mtime = stat.mtime;
@@ -147,25 +150,26 @@ Dirstate* Dirstatecache::get(

if (request_thgstatus_update)
{
- TDEBUG_TRACE("Dirstatecache::get: calling Thgstatus::update");
+ TDEBUG_TRACEW(L"Dirstatecache::get: calling Thgstatus::update");
Thgstatus::update(cwd);
}
else
{
- TDEBUG_TRACE("Dirstatecache::get: omitting Thgstatus::update");
+ TDEBUG_TRACEW(L"Dirstatecache::get: omitting Thgstatus::update");
}

return iter->dstate;
}


-void Dirstatecache::invalidate(const std::string& hgroot)
+void Dirstatecache::invalidate(const std::wstring& hgroot)
{
typedef std::list<E>::iterator Iter;

if (hgroot.empty())
+ {
return;
-
+ }
for (Iter i = cache().begin(); i != cache().end(); ++i)
{
if (hgroot == i->hgroot)
@@ -173,7 +177,7 @@ void Dirstatecache::invalidate(const std
delete i->dstate;
i->dstate = 0;
cache().erase(i);
- TDEBUG_TRACE("Dirstatecache::invalidate(" << hgroot << ")");
+ TDEBUG_TRACEW(L"Dirstatecache::invalidate(" << hgroot << ")");
break;
}
}
diff --git a/win32/shellext/Dirstatecache.h b/win32/shellext/Dirstatecache.h
--- a/win32/shellext/Dirstatecache.h
+++ b/win32/shellext/Dirstatecache.h
@@ -31,25 +31,28 @@ class Dirstatecache
__int64 dstate_mtime;
__int64 dstate_size;

- std::string hgroot;
+ std::wstring hgroot;
unsigned tickcount;
bool unset;

- E():
- dstate(0),
- dstate_mtime(0),
- dstate_size(0),
+ E():
+ dstate(0),
+ dstate_mtime(0),
+ dstate_size(0),
tickcount(0),
unset(false)
- {}
+ {}
};

static std::list<E>& cache();

public:
static Dirstate* get(
- const std::string& hgroot, const std::string& cwd, bool& unset);
- static void invalidate(const std::string& hgroot);
+ const std::wstring& hgroot,
+ const std::wstring& cwd,
+ bool& unset
+ );
+ static void invalidate(const std::wstring& hgroot);
};

#endif
diff --git a/win32/shellext/IconBitmapUtils.cpp b/win32/shellext/IconBitmapUtils.cpp
--- a/win32/shellext/IconBitmapUtils.cpp
+++ b/win32/shellext/IconBitmapUtils.cpp
@@ -109,7 +109,7 @@ HBITMAP IconBitmapUtils::IconToBitmapPAR

if (pfnBeginBufferedPaint == NULL || pfnEndBufferedPaint == NULL || pfnGetBufferedPaintBits == NULL)
{
- TDEBUG_TRACE(" IconBitmapUtils::IconToBitmapPARGB32: Theme functions not found, returns NULL");
+ TDEBUG_TRACEW(L" IconBitmapUtils::IconToBitmapPARGB32: Theme functions not found, returns NULL");
return NULL;
}

diff --git a/win32/shellext/InitStatus.cpp b/win32/shellext/InitStatus.cpp
--- a/win32/shellext/InitStatus.cpp
+++ b/win32/shellext/InitStatus.cpp
@@ -27,34 +27,34 @@ InitStatus& InitStatus::inst()
}


-void InitStatus::add(std::string& s, const char* missing)
+void InitStatus::add(std::wstring& s, const wchar_t* missing)
{
if (!s.empty())
- s += ", ";
+ s += L", ";
s += missing;
}


-std::string InitStatus::check()
+std::wstring InitStatus::check()
{
const InitStatus& self = inst();
- std::string missing;
+ std::wstring missing;

if (self.unchanged_ == 0)
- add(missing, "unchanged");
+ add(missing, L"unchanged");
if (self.added_ == 0)
- add(missing, "added");
+ add(missing, L"added");
if (self.modified_ == 0)
- add(missing, "modified");
+ add(missing, L"modified");
if (self.notinrepo_ == 0)
- add(missing, "notinrepo");
+ add(missing, L"notinrepo");

if (missing.empty())
- return "";
+ return L"";

- std::string reason = "uninitialized handlers: " + missing;
+ std::wstring reason = L"uninitialized handlers: " + missing;
Thgstatus::error(reason);
- std::string res = "InitStatus: error: " + reason;
- TDEBUG_TRACE("***** " << res);
+ std::wstring res = L"InitStatus: error: " + reason;
+ TDEBUG_TRACEW(L"***** " << res);
return res;
}
diff --git a/win32/shellext/InitStatus.h b/win32/shellext/InitStatus.h
--- a/win32/shellext/InitStatus.h
+++ b/win32/shellext/InitStatus.h
@@ -25,11 +25,11 @@ public:
int notinrepo_;

static InitStatus& inst();
- static std::string check();
+ static std::wstring check();

private:
InitStatus()
: unchanged_(0), added_(0), modified_(0), notinrepo_(0) {}

- static void add(std::string& s, const char* missing);
+ static void add(std::wstring& s, const wchar_t* missing);
};
diff --git a/win32/shellext/Makefile.nmake b/win32/shellext/Makefile.nmake
--- a/win32/shellext/Makefile.nmake
+++ b/win32/shellext/Makefile.nmake
@@ -4,6 +4,7 @@ OBJECTS_DIRSTATE = TortoiseUtils.obj \
Directory.obj \
Winstat.obj \
RegistryConfig.obj \
+ StringUtils.obj \
ThgDebug.obj

OBJECTS_THGSGELL = $(OBJECTS_DIRSTATE) \
@@ -27,6 +28,7 @@ OBJECTS_THGSGELL = $(OBJECTS_DIRSTATE) \

OBJECTS_TERMINATE = Thgstatus.obj \
RegistryConfig.obj \
+ StringUtils.obj \
ThgDebug.obj

LIBS = shlwapi.lib gdiplus.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Msi.lib
@@ -35,7 +37,7 @@ DEFFILE = ShellExt.def

# /MT = statically linked runtime libraries /MD = dynamically linked
# THG_EXTRA_CPPFLAGS is taken from environment (may be undefined)
-CPPFLAGS = /nologo /Ox /W2 /EHsc /MT /DAPPMAIN /DTHG_DEBUG $(THG_EXTRA_CPPFLAGS)
+CPPFLAGS = /D "_UNICODE" /D "UNICODE" /nologo /Ox /W2 /EHsc /MT /DAPPMAIN /DTHG_DEBUG $(THG_EXTRA_CPPFLAGS) $(THG_UTF8_ASSUMING_CPPFLAGS)
BASE_LDFLAGS = /nologo /INCREMENTAL:NO /MANIFEST $(LIBS)
LDFLAGS_THGSHELL = $(BASE_LDFLAGS) /DLL /DEF:$(DEFFILE)
LDFLAGS_DIRSTATE = $(BASE_LDFLAGS) /SUBSYSTEM:CONSOLE
@@ -66,3 +68,4 @@ dirstate.exe: dirstate.obj $(OBJECTS_DIR
$(TERMINATE_TARGET): terminate.obj $(OBJECTS_TERMINATE)
link /OUT:$@ $(LDFLAGS_TERMINATE) $**
mt -nologo -manifest $@.manifest -outputresource:"$@;#1"
+
diff --git a/win32/shellext/QueryDirstate.cpp b/win32/shellext/QueryDirstate.cpp
--- a/win32/shellext/QueryDirstate.cpp
+++ b/win32/shellext/QueryDirstate.cpp
@@ -27,32 +27,31 @@

#include <shlwapi.h>

-
class QueryState
{
public:
- std::string path;
- bool isdir;
- std::string basedir;
- std::string hgroot;
+ std::wstring path;
+ bool isdir;
+ std::wstring basedir;
+ std::wstring hgroot;

- char status;
- unsigned tickcount;
+ wchar_t status;
+ unsigned tickcount;

QueryState(): isdir(false), status('0'), tickcount(0) {}
};


-bool hasHgDir(char cls, const std::string& path, unsigned& ticks)
+bool hasHgDir(wchar_t cls, const std::wstring& path, unsigned& ticks)
{
ticks = 0;

bool res = false;

- if (path.empty() || path == "\\")
+ if (path.empty() || path == L"\\")
return res;

- const std::string p = path + "\\.hg";
+ const std::wstring p = path + L"\\.hg";

if (::PathIsUNCServerShare(p.c_str()))
return res;
@@ -66,9 +65,9 @@ bool hasHgDir(char cls, const std::strin
if (ticks > 5 /* ms */)
{
// trace slower PathIsDirectory calls (untypical on local discs)
- TDEBUG_TRACE(
- "[" << cls << "] hasHgDir: PathIsDirectory(\"" << p << "\")" <<
- " -> " << res << ", in " << ticks << " ticks"
+ TDEBUG_TRACEW(
+ L"[" << cls << L"] hasHgDir: PathIsDirectory(\"" << p << L"\")" <<
+ L" -> " << res << L", in " << ticks << L" ticks"
);
}

@@ -76,14 +75,14 @@ bool hasHgDir(char cls, const std::strin
}


-int findHgRoot(char cls, QueryState& cur, QueryState& last, bool outdated)
+int findHgRoot(wchar_t cls, QueryState& cur, QueryState& last, bool outdated)
{
- std::string dp = "["; dp += cls; dp += "] findHgRoot";
+ std::wstring dp = L"["; dp += cls; dp += L"] findHgRoot";

{
- std::string p = cur.path;
- p.push_back('\\');
- if (p.find("\\.hg\\") != std::string::npos)
+ std::wstring p = cur.path;
+ p.push_back(L'\\');
+ if (p.find(L"\\.hg\\") != std::wstring::npos)
{
// ignore files and dirs named '.hg'
last = cur;
@@ -91,9 +90,9 @@ int findHgRoot(char cls, QueryState& cur
}
}

- if (!outdated && !last.hgroot.empty()
+ if (!outdated && !last.hgroot.empty()
&& cur.path.size() >= last.hgroot.size()
- && StartsWith(cur.path, last.hgroot + "\\"))
+ && StartsWith(cur.path, last.hgroot + L"\\"))
{
cur.hgroot = last.hgroot;
return 1;
@@ -117,7 +116,7 @@ int findHgRoot(char cls, QueryState& cur
if (has_hg)
{
cur.hgroot = cur.path;
- TDEBUG_TRACE(dp << "(" << cur.path << "): hgroot = cur.path");
+ TDEBUG_TRACEW(dp << L"(" << cur.path << L"): hgroot = cur.path");
return 1;
}
}
@@ -130,27 +129,27 @@ int findHgRoot(char cls, QueryState& cur
return 1;
}

- for (std::string p = cur.basedir;;)
+ for (std::wstring p = cur.basedir;;)
{
bool has_hg = hasHgDir(cls, p, ticks);
if (ticks > 5000 /* ms */)
{
- const std::string reason = "ignoring slow \"" + p + "\"";
+ const std::wstring reason = L"ignoring slow \"" + p + L"\"";
Thgstatus::error(reason);
file_access_is_unacceptably_slow = true;
goto exit;
}

- if (has_hg)
+ if (has_hg)
{
cur.hgroot = p;
- TDEBUG_TRACE(
- dp << "(" << cur.path << "): hgroot = '" << cur.hgroot
- << "' (found repo)"
+ TDEBUG_TRACEW(
+ dp << L"(" << cur.path << L"): hgroot = '" << cur.hgroot
+ << L"' (found repo)"
);
return 1;
}
- std::string p2 = DirName(p);
+ std::wstring p2 = DirName(p);
if (p2.size() == p.size())
break;
p.swap(p2);
@@ -159,13 +158,13 @@ int findHgRoot(char cls, QueryState& cur
exit:
if (file_access_is_unacceptably_slow)
{
- TDEBUG_TRACE(
- "******" << dp << "(" << cur.path << "): ignored, "
- << "call took too long (" << ticks << " ticks)");
+ TDEBUG_TRACEW(
+ L"******" << dp << L"(" << cur.path << L"): ignored, "
+ << L"call took too long (" << ticks << L" ticks)");
}
else
{
- TDEBUG_TRACE(dp << "(" << cur.path << "): NO repo found");
+ TDEBUG_TRACEW(dp << L"(" << cur.path << L"): NO repo found");
}
last = cur;
return 0;
@@ -173,9 +172,9 @@ exit:


int get_relpath(
- const std::string& hgroot,
- const std::string& path,
- std::string& res
+ const std::wstring& hgroot,
+ const std::wstring& path,
+ std::wstring& res
)
{
size_t offset = hgroot.size();
@@ -185,24 +184,23 @@ int get_relpath(
if (offset > path.size())
return 0;

- if (path[offset] == '\\')
+ if (path[offset] == L'\\')
offset++;
-
- const char* relpathptr = path.c_str() + offset;
+
+ const wchar_t* relpathptr = path.c_str() + offset;

res = relpathptr;
return 1;
}

-
int HgQueryDirstate(
const char cls,
- const std::string& path,
- const char& filterStatus,
+ const std::wstring& path,
+ const wchar_t& filterStatus,
char& outStatus
)
{
- std::string dp = "["; dp += cls; dp += "] HgQueryDirstate: ";
+ std::wstring dp = L"["; dp += cls; dp += L"] HgQueryDirstate: ";

static QueryState last;

@@ -216,7 +214,7 @@ int HgQueryDirstate(

const bool outdated = cur.tickcount - last.tickcount > 2000;

- if (!outdated && last.path == path)
+ if (!outdated && last.path == path)
{
outStatus = last.status;
if (outStatus == 'P')
@@ -241,19 +239,21 @@ int HgQueryDirstate(
return 0;
}

- if (path[offset] == '\\')
+ if (path[offset] == L'\\')
offset++;
- const char* relpathptr = path.c_str() + offset;
+ const wchar_t* relpathptr = path.c_str() + offset;

- std::string relpath = relpathptr;
+ std::wstring relpath = relpathptr;

for (size_t i = 0; i < relpath.size(); ++i)
{
- if (relpath[i] == '\\')
- relpath[i] = '/';
+ if (relpath[i] == L'\\')
+ relpath[i] = L'/';
}

- DirectoryStatus* pdirsta = DirectoryStatus::get(cur.hgroot, cur.basedir);
+ // read .hg/thgstatus
+ DirectoryStatus* pdirsta = DirectoryStatus::get(
+ cur.hgroot, cur.basedir);
if (pdirsta && pdirsta->noicons())
{
last = cur;
@@ -271,21 +271,22 @@ int HgQueryDirstate(

bool unset = false;

+ // read .hg/dirstate
Dirstate* pds = Dirstatecache::get(cur.hgroot, cur.basedir, unset);
if (!pds)
{
- TDEBUG_TRACE(
- dp << "Dirstatecache::get(" << cur.hgroot
- << ") returns no Dirstate"
+ TDEBUG_TRACEW(
+ dp << L"Dirstatecache::get(" << cur.hgroot
+ << L") returns no Dirstate"
);
last = cur;
return 0;
}

Winstat stat;
- if (0 != stat.lstat(path.c_str()))
+ if (0 != stat.lstat(path.c_str()))
{
- TDEBUG_TRACE(dp << "lstat(" << path << ") failed");
+ TDEBUG_TRACEW(dp << L"lstat(" << path << L") failed");
last = cur;
return 0;
}
@@ -313,7 +314,7 @@ int HgQueryDirstate(
}

const Direntry* const e = pds->root().get(relpath);
- if (!e)
+ if (!e)
{
last = cur;
return 0;
@@ -328,17 +329,17 @@ int HgQueryDirstate(

if (outStatus == 'M')
{
- std::string relbase;
+ std::wstring relbase;
if (pdirsta && get_relpath(cur.hgroot, cur.basedir, relbase))
{
- TDEBUG_TRACE(dp << "relbase = '" << relbase << "'");
+ TDEBUG_TRACEW(dp << L"relbase = '" << relbase << L"'");

char basedir_status = pdirsta->status(relbase);
- TDEBUG_TRACE(dp << "basedir_status = " << basedir_status);
+ TDEBUG_TRACEW(dp << L"basedir_status = " << basedir_status);

if (basedir_status != 'M')
update = true;
- }
+ }
}
else if (outStatus == 'P')
{
@@ -353,12 +354,12 @@ int HgQueryDirstate(
lasttickcount = tc;
}

- TDEBUG_TRACE(dp << "outStatus is 'P'");
+ TDEBUG_TRACEW(dp << L"outStatus is 'P'");
}

if (update)
{
- TDEBUG_TRACE(dp << "calling Thgstatus::update");
+ TDEBUG_TRACEW(dp << L"calling Thgstatus::update");
Thgstatus::update(path);
}

diff --git a/win32/shellext/QueryDirstate.h b/win32/shellext/QueryDirstate.h
--- a/win32/shellext/QueryDirstate.h
+++ b/win32/shellext/QueryDirstate.h
@@ -5,8 +5,8 @@

int HgQueryDirstate(
const char myClass,
- const std::string& path,
- const char& filterStatus,
+ const std::wstring& path,
+ const wchar_t& filterStatus,
char& outStatus
);

diff --git a/win32/shellext/RegistryConfig.cpp b/win32/shellext/RegistryConfig.cpp
--- a/win32/shellext/RegistryConfig.cpp
+++ b/win32/shellext/RegistryConfig.cpp
@@ -1,27 +1,27 @@
#include "stdafx.h"
#include "RegistryConfig.h"

-int GetRegistryConfig(const std::string& name, std::string& res)
+int GetRegistryConfig(const std::wstring& name, std::wstring& res)
{
- const char* const subkey = "Software\\TortoiseHg";
+ const wchar_t* const subkey = L"Software\\TortoiseHg";

HKEY hkey = 0;
- LONG rv = RegOpenKeyExA(
+ LONG rv = RegOpenKeyEx(
HKEY_CURRENT_USER, subkey, 0, KEY_READ, &hkey);

if (rv != ERROR_SUCCESS || hkey == 0)
return 0;

- BYTE Data[MAX_PATH] = "";
+ BYTE Data[MAX_PATH * 2] = {0};
DWORD cbData = MAX_PATH * sizeof(BYTE);

- rv = RegQueryValueExA(
+ rv = RegQueryValueEx(
hkey, name.c_str(), 0, 0, Data, &cbData);

int ret = 0;
if (rv == ERROR_SUCCESS)
{
- res = reinterpret_cast<const char*>(&Data);
+ res = reinterpret_cast<const wchar_t*>(&Data);
ret = 1;
}

diff --git a/win32/shellext/RegistryConfig.h b/win32/shellext/RegistryConfig.h
--- a/win32/shellext/RegistryConfig.h
+++ b/win32/shellext/RegistryConfig.h
@@ -3,6 +3,6 @@

#include <string>

-int GetRegistryConfig(const std::string& name, std::string& res);
+int GetRegistryConfig(const std::wstring& name, std::wstring& res);

#endif
diff --git a/win32/shellext/ShellExt.cpp b/win32/shellext/ShellExt.cpp
--- a/win32/shellext/ShellExt.cpp
+++ b/win32/shellext/ShellExt.cpp
@@ -41,14 +41,14 @@ BOOL WINAPI DllMain(HINSTANCE hInstance,
{
if (dwReason == DLL_PROCESS_ATTACH)
{
- TDEBUG_TRACE("DllMain: DLL_PROCESS_ATTACH");
+ TDEBUG_TRACEW("DllMain: DLL_PROCESS_ATTACH");
CShellExt::hModule_ = hInstance;
::InitializeCriticalSection(CShellExt::GetCriticalSection());
_LoadResources();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
- TDEBUG_TRACE("DllMain: DLL_PROCESS_ATTACH");
+ TDEBUG_TRACEW(L"DllMain: DLL_PROCESS_ATTACH");
::DeleteCriticalSection(CShellExt::GetCriticalSection());
_UnloadResources();
}
@@ -59,7 +59,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstance,

STDAPI DllCanUnloadNow(void)
{
- TDEBUG_TRACE("DllCanUnloadNow");
+ TDEBUG_TRACEW(L"DllCanUnloadNow");
return (CShellExt::GetRefCount() == 0 ? S_OK : S_FALSE);
}

@@ -74,11 +74,11 @@ STDAPI DllGetClassObject(REFCLSID rclsid
::CoTaskMemFree(ptr);
}

- TDEBUG_TRACEW("DllGetClassObject clsid = " << clsid);
+ TDEBUG_TRACEW(L"DllGetClassObject clsid = " << clsid);

if (ppvOut == 0)
{
- TDEBUG_TRACE("**** DllGetClassObject: error: ppvOut is 0");
+ TDEBUG_TRACEW(L"**** DllGetClassObject: error: ppvOut is 0");
return E_POINTER;
}

@@ -91,40 +91,40 @@ STDAPI DllGetClassObject(REFCLSID rclsid
if (clsid == CLSID_TortoiseHgCmenu)
{
FactCmenu *pcf = new FactCmenu(0);
- TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgCmenu");
+ TDEBUG_TRACEW(L"DllGetClassObject clsname = " << L"CLSID_TortoiseHgCmenu");
return pcf->QueryInterface(riid, ppvOut);
}
else if (clsid == CLSID_TortoiseHgDropHandler)
{
FactDnd *pcf = new FactDnd(0);
- TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgDropHandler");
+ TDEBUG_TRACEW(L"DllGetClassObject clsname = " << L"CLSID_TortoiseHgDropHandler");
return pcf->QueryInterface(riid, ppvOut);
}
else if (clsid == CLSID_TortoiseHgNormal)
{
FactOvl *pcf = new FactOvl('C'); // clean
- TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgNormal");
+ TDEBUG_TRACEW(L"DllGetClassObject clsname = " << L"CLSID_TortoiseHgNormal");
++InitStatus::inst().unchanged_;
return pcf->QueryInterface(riid, ppvOut);
}
else if (clsid == CLSID_TortoiseHgAdded)
{
FactOvl *pcf = new FactOvl('A'); // added
- TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgAdded");
+ TDEBUG_TRACEW(L"DllGetClassObject clsname = " << L"CLSID_TortoiseHgAdded");
++InitStatus::inst().added_;
return pcf->QueryInterface(riid, ppvOut);
}
else if (clsid == CLSID_TortoiseHgModified)
{
FactOvl *pcf = new FactOvl('M'); // modified
- TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgModified");
+ TDEBUG_TRACEW(L"DllGetClassObject clsname = " << L"CLSID_TortoiseHgModified");
++InitStatus::inst().modified_;
return pcf->QueryInterface(riid, ppvOut);
}
else if (clsid == CLSID_TortoiseHgUnversioned)
{
FactOvl *pcf = new FactOvl('?'); // not in repo
- TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgUnversioned");
+ TDEBUG_TRACEW(L"DllGetClassObject clsname = " << L"CLSID_TortoiseHgUnversioned");
++InitStatus::inst().notinrepo_;
return pcf->QueryInterface(riid, ppvOut);
}
diff --git a/win32/shellext/StringUtils.cpp b/win32/shellext/StringUtils.cpp
--- a/win32/shellext/StringUtils.cpp
+++ b/win32/shellext/StringUtils.cpp
@@ -15,15 +15,17 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

+#include "stdafx.h"
#include "StringUtils.h"

#include <vector>

+#define FLAG_DEBUG_THG_MB_TO_WIDE 0

// Quotes a string
-std::string Quote(const std::string& str)
+std::wstring Quote(const std::wstring& str)
{
- std::string sResult = "\"" + str + "\"";
+ std::wstring sResult = L"\"" + str + L"\"";
return sResult;
}

@@ -49,14 +51,16 @@ std::string WideToMultibyte(const std::w
}


-// Convert multibyte string to Unicode string
-std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage)
+// Convert multibyte string to Unicode string
+std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage, DWORD dwFlags)
{
int ret = MultiByteToWideChar(
- CodePage, 0, multibyte.c_str(),
+ CodePage, dwFlags, multibyte.c_str(),
static_cast<int>(multibyte.length()), 0, 0
);

+ if ( ret == 0 ) { return L"" ; }
+
std::vector<wchar_t> wide(ret + 1);

ret = MultiByteToWideChar(
@@ -67,3 +71,22 @@ std::wstring MultibyteToWide(const std::

return &wide[0];
}
+
+// Convert multibyte string to Unicode string of .hg/dirstate and .hg/thgstatus
+std::wstring ThgMultibyteToWide (
+ const std::string& multibyte,
+ UINT CodePage
+ )
+{
+ std::wstring wc = L"";
+ if (wc == L"")
+ {
+ wc = MultibyteToWide(multibyte, CodePage, 0);
+ if (FLAG_DEBUG_THG_MB_TO_WIDE)
+ {
+ TDEBUG_TRACEW(L"hg file CP" << CodePage << ": " << wc);
+ }
+ }
+ return wc;
+}
+
diff --git a/win32/shellext/StringUtils.h b/win32/shellext/StringUtils.h
--- a/win32/shellext/StringUtils.h
+++ b/win32/shellext/StringUtils.h
@@ -22,13 +22,19 @@
#include <windows.h>

// Quotes a string
-std::string Quote(const std::string& str);
+std::wstring Quote(const std::wstring& str);

// Convert Unicode string to multibyte string
std::string WideToMultibyte(const std::wstring& wide, UINT CodePage = CP_ACP);

// Convert multibyte string to Unicode string
-std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage = CP_ACP);
+std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage, DWORD dwFlags);

+// Convert multibyte string to Unicode string of .hg/dirstate and .hg/thgstatus
+// .hg/dirstate and .hg/thgstatus are written in multibyte.
+std::wstring ThgMultibyteToWide(
+ const std::string& multibyte,
+ UINT CodePage = CP_ACP
+ );

#endif
diff --git a/win32/shellext/ThgDebug.cpp b/win32/shellext/ThgDebug.cpp
--- a/win32/shellext/ThgDebug.cpp
+++ b/win32/shellext/ThgDebug.cpp
@@ -6,13 +6,14 @@
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.

+#include "stdafx.h"
#include "ThgDebug.h"
#include "RegistryConfig.h"

bool ThgDebug::regDebugShellExt()
{
- std::string val;
- return GetRegistryConfig("DebugShellExt", val) != 0 && val == "1";
+ std::wstring val;
+ return GetRegistryConfig(L"DebugShellExt", val) != 0 && val == L"1";
}

bool ThgDebug::enabled()
diff --git a/win32/shellext/ThgVersion.cpp b/win32/shellext/ThgVersion.cpp
--- a/win32/shellext/ThgVersion.cpp
+++ b/win32/shellext/ThgVersion.cpp
@@ -1,3 +1,4 @@
+#include "stdafx.h"
#include "ThgVersion.h"
#include "parentid.h"

diff --git a/win32/shellext/Thgstatus.cpp b/win32/shellext/Thgstatus.cpp
--- a/win32/shellext/Thgstatus.cpp
+++ b/win32/shellext/Thgstatus.cpp
@@ -17,36 +17,42 @@
#include "stdafx.h"

#include "Thgstatus.h"
+#include "StringUtils.h"

#include <vector>


-std::string GetPipeName()
+std::wstring GetPipeName()
{
DWORD size = 260;
- std::vector<char> buf(size);
- if (!::GetUserNameA(&buf[0], &size))
- return "";
- std::string res = "\\\\.\\pipe\\TortoiseHgRpcServer-bc0c27107423-";
+ std::vector<wchar_t> buf(size);
+ if (!::GetUserName(&buf[0], &size))
+ return L"";
+ std::wstring res = L"\\\\.\\pipe\\TortoiseHgRpcServer-bc0c27107423-";
res += &buf[0];
return res;
}

-
-int Thgstatus::SendRequest(const std::string& request)
+int Thgstatus::SendRequest(const std::wstring& request)
{
- static const std::string pname = GetPipeName();
+ static const std::wstring pname = GetPipeName();
+ static const std::string pname_a = WideToMultibyte(pname, CP_ACP);
+ std::string request_a;

if (pname.empty())
+ {
return 0;
+ }
+
+ request_a = WideToMultibyte(request, CP_ACP);

BOOL fSuccess;
DWORD cbRead;

- TDEBUG_TRACE("Thgstatus::update: sending '" << request << "' to " << pname);
+ TDEBUG_TRACEW(L"Thgstatus::update: sending '" << request << "' to " << pname);

fSuccess = ::CallNamedPipeA(
- pname.c_str(), (void*)request.c_str(), request.size(), 0, 0, &cbRead,
+ pname_a.c_str(), (void*)request_a.c_str(), request_a.size(), 0, 0, &cbRead,
NMPWAIT_NOWAIT
);

@@ -57,14 +63,14 @@ int Thgstatus::SendRequest(const std::st
}
else if (err == ERROR_PIPE_BUSY)
{
- TDEBUG_TRACE("Thgstatus::update: CallNamedPipeA failed. "
- "ERROR_PIPE_BUSY");
+ TDEBUG_TRACEW(L"Thgstatus::update: CallNamedPipe failed. "
+ L"ERROR_PIPE_BUSY");
return -1;
}
else
{
- TDEBUG_TRACE("Thgstatus::update: CallNamedPipeA failed ("
- << err << ")");
+ TDEBUG_TRACEW(L"Thgstatus::update: CallNamedPipe failed ("
+ << err << L")");
return -1;
}
}
diff --git a/win32/shellext/Thgstatus.h b/win32/shellext/Thgstatus.h
--- a/win32/shellext/Thgstatus.h
+++ b/win32/shellext/Thgstatus.h
@@ -21,20 +21,20 @@

class Thgstatus
{
- static int SendRequest(const std::string& request);
+ static int SendRequest(const std::wstring& request);

public:
- static int update(const std::string& path) {
- return SendRequest("update|" + path);
+ static int update(const std::wstring& path) {
+ return SendRequest(L"update|" + path);
}
- static int remove(const std::string& path) {
- return SendRequest("remove|" + path);
+ static int remove(const std::wstring& path) {
+ return SendRequest(L"remove|" + path);
}
- static int error(const std::string& text) {
- return SendRequest("error|" + text);
+ static int error(const std::wstring& text) {
+ return SendRequest(L"error|" + text);
}
static int terminate() {
- return SendRequest("terminate|");
+ return SendRequest(L"terminate|");
}
};

diff --git a/win32/shellext/TortoiseIconBitmap.cpp b/win32/shellext/TortoiseIconBitmap.cpp
--- a/win32/shellext/TortoiseIconBitmap.cpp
+++ b/win32/shellext/TortoiseIconBitmap.cpp
@@ -6,10 +6,10 @@
#include "IconBitmapUtils.h"


-HBITMAP GetTortoiseIconBitmap(const std::string& iconname)
+HBITMAP GetTortoiseIconBitmap(const std::wstring& iconname)
{
IconBitmapUtils bmpUtils;
- typedef std::map<std::string, HBITMAP> BitmapCacheT;
+ typedef std::map<std::wstring, HBITMAP> BitmapCacheT;
static BitmapCacheT bmpcache_;

BitmapCacheT::const_iterator i = bmpcache_.find(iconname);
@@ -18,7 +18,7 @@ HBITMAP GetTortoiseIconBitmap(const std:

if (bmpcache_.size() > 200)
{
- TDEBUG_TRACE("**** GetTortoiseIconBitmap: error: too many bitmaps in cache");
+ TDEBUG_TRACEW(L"**** GetTortoiseIconBitmap: error: too many bitmaps in cache");
return 0;
}

@@ -29,15 +29,15 @@ HBITMAP GetTortoiseIconBitmap(const std:
HBITMAP hBmp = bmpUtils.IconToBitmapPARGB32(hIcon);
if (!hBmp)
{
- TDEBUG_TRACE("**** GetTortoiseIconBitmap: error: something wrong in bmpUtils.ConvertToPARGB32(hIcon)");
+ TDEBUG_TRACEW(L"**** GetTortoiseIconBitmap: error: something wrong in bmpUtils.ConvertToPARGB32(hIcon)");
return 0;
}

bmpcache_[iconname] = hBmp;

- TDEBUG_TRACE(
- "GetTortoiseIconBitmap: added '" << iconname << "' to bmpcache_"
- " (" << bmpcache_.size() << " bitmaps in cache)"
+ TDEBUG_TRACEW(
+ L"GetTortoiseIconBitmap: added '" << iconname << L"' to bmpcache_"
+ L" (" << bmpcache_.size() << L" bitmaps in cache)"
);

return hBmp;
diff --git a/win32/shellext/TortoiseIconBitmap.h b/win32/shellext/TortoiseIconBitmap.h
--- a/win32/shellext/TortoiseIconBitmap.h
+++ b/win32/shellext/TortoiseIconBitmap.h
@@ -4,6 +4,6 @@
#include <windows.h>
#include <string>

-HBITMAP GetTortoiseIconBitmap(const std::string& iconname);
+HBITMAP GetTortoiseIconBitmap(const std::wstring& iconname);

#endif
diff --git a/win32/shellext/TortoiseUtils.cpp b/win32/shellext/TortoiseUtils.cpp
--- a/win32/shellext/TortoiseUtils.cpp
+++ b/win32/shellext/TortoiseUtils.cpp
@@ -10,38 +10,15 @@

#include "shlwapi.h"

-
-LPWSTR hf_mbtowc(LPWSTR lpw, LPCSTR lpa, int nChars)
+std::wstring GetTHgProgRoot()
{
- assert(lpa != NULL);
- assert(lpw != NULL);
-
- lpw[0] = '\0';
- MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);
- return lpw;
-}
-
-
-LPSTR hf_wctomb(LPSTR lpa, LPCWSTR lpw, int nChars)
-{
- assert(lpw != NULL);
- assert(lpa != NULL);
-
- lpa[0] = '\0';
- WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL);
- return lpa;
-}
-
-
-std::string GetTHgProgRoot()
-{
- LPCSTR regname = "Software\\TortoiseHg";
+ LPCWSTR regname = L"Software\\TortoiseHg";
HKEY key = HKEY_LOCAL_MACHINE;
- TCHAR lpszValue[MAX_PATH] = "";
+ TCHAR lpszValue[MAX_PATH] = L"";
LONG lpcbLonger = MAX_PATH * sizeof(TCHAR);

if (RegQueryValue(key, regname, lpszValue, &lpcbLonger) != ERROR_SUCCESS)
- return "";
+ return L"";

return lpszValue;
}
@@ -51,32 +28,32 @@ std::string GetTHgProgRoot()
// 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 std::string& command, const std::string& cwd)
+bool LaunchCommand(const std::wstring& command, const std::wstring& cwd)
{
- TDEBUG_TRACE("LaunchCommand: " << command);
- TDEBUG_TRACE("LaunchCommand: in " << cwd);
+ TDEBUG_TRACEW(L"LaunchCommand: " << command);
+ TDEBUG_TRACEW(L"LaunchCommand: in " << cwd);
PROCESS_INFORMATION processInfo;
memset(&processInfo, 0, sizeof(processInfo));

- STARTUPINFOA startupInfo;
+ STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));

- int res = CreateProcessA(
+ int res = CreateProcess(
NULL, // No module name, use command line
- const_cast<char*>(command.c_str()),
+ const_cast<wchar_t*>(command.c_str()),
NULL, // Process handle not inherited
NULL, // Thread handle not inherited
FALSE,
CREATE_NO_WINDOW,
NULL, // use parent's environment
- const_cast<char*>(cwd.c_str()),
+ const_cast<wchar_t*>(cwd.c_str()),
&startupInfo,
&processInfo
);

if (res == 0)
{
- TDEBUG_TRACE("LaunchCommand: failed to launch");
+ TDEBUG_TRACEW(L"LaunchCommand: failed to launch");
return false;
}

@@ -85,14 +62,14 @@ bool LaunchCommand(const std::string& co
return true;
}

-std::string GetTemporaryFile(LPCTSTR prefix)
+std::wstring GetTemporaryFile(LPCWSTR prefix)
{
- char tempDir[MAX_PATH + 1];
- char tempFile[MAX_PATH + 1];
+ wchar_t tempDir[MAX_PATH + 1];
+ wchar_t tempFile[MAX_PATH + 1];

if (GetTempPath(MAX_PATH, tempDir) == 0)
{
- TDEBUG_TRACE("GetTemporaryFile: Failed to find temporary path");
+ TDEBUG_TRACEW(L"GetTemporaryFile: Failed to find temporary path");
}
else if (GetTempFileName(tempDir, prefix, 0, tempFile) != 0)
{
@@ -100,57 +77,57 @@ std::string GetTemporaryFile(LPCTSTR pre
}
else
{
- TDEBUG_TRACE("GetTemporaryFile: Failed to get temporary file");
+ TDEBUG_TRACEW(L"GetTemporaryFile: Failed to get temporary file");
}

- return "";
+ return L"";
}


-bool IsDirectory(const std::string& filename)
+bool IsDirectory(const std::wstring& filename)
{
return ::PathIsDirectory(filename.c_str()) != 0;
}


-std::string DirName(const std::string& filename)
+std::wstring DirName(const std::wstring& filename)
{
if (filename.empty())
return filename;
- std::string::size_type pos = filename.find_last_of("\\");
- if (pos == std::string::npos)
- return "";
- std::string myfilename = filename.substr(0, pos);
- if (myfilename.size() > 0 && myfilename[myfilename.size()-1] == ':')
- myfilename.push_back('\\');
+ std::wstring::size_type pos = filename.find_last_of(L"\\");
+ if (pos == std::wstring::npos)
+ return L"";
+ std::wstring myfilename = filename.substr(0, pos);
+ if (myfilename.size() > 0 && myfilename[myfilename.size()-1] == L':')
+ myfilename.push_back(L'\\');
return myfilename;
}

-std::string BaseName(const std::string& filename)
+std::wstring BaseName(const std::wstring& filename)
{
if (filename.empty())
return filename;
- std::string::size_type pos = filename.find_last_of("\\");
- if (pos == std::string::npos)
+ std::wstring::size_type pos = filename.find_last_of(L"\\");
+ if (pos == std::wstring::npos)
return filename;
return filename.substr(pos+1);
}


// not reentrant
-HICON GetTortoiseIcon(const std::string& iconname)
+HICON GetTortoiseIcon(const std::wstring& iconname)
{
- typedef std::map<std::string, HICON> IconCacheT;
+ typedef std::map<std::wstring, HICON> IconCacheT;
static IconCacheT iconcache_;

- std::string thgdir = GetTHgProgRoot();
+ std::wstring thgdir = GetTHgProgRoot();
if (thgdir.empty())
{
- TDEBUG_TRACE("GetTortoiseIcon: THG root is empty");
+ TDEBUG_TRACEW(L"GetTortoiseIcon: THG root is empty");
return 0;
}

- const std::string iconpath = thgdir + "\\icons\\" + iconname;
+ const std::wstring iconpath = thgdir + L"\\icons\\" + iconname;

IconCacheT::const_iterator i = iconcache_.find(iconpath);
if (i != iconcache_.end())
@@ -158,48 +135,48 @@ HICON GetTortoiseIcon(const std::string&

if (iconcache_.size() > 200)
{
- TDEBUG_TRACE("**** GetTortoiseIcon: error: too many icons in cache");
+ TDEBUG_TRACEW(L"**** GetTortoiseIcon: error: too many icons in cache");
return 0;
}

- HICON h = (HICON) LoadImageA(0, iconpath.c_str(), IMAGE_ICON,
+ HICON h = (HICON) LoadImage(0, iconpath.c_str(), IMAGE_ICON,
16, 16, LR_LOADFROMFILE);
if (!h)
{
- TDEBUG_TRACE("GetTortoiseIcon: can't find " + iconpath);
+ TDEBUG_TRACEW(L"GetTortoiseIcon: can't find " + iconpath);
return 0;
}

iconcache_[iconpath] = h;

- TDEBUG_TRACE(
- "GetTortoiseIcon: added '" << iconpath << "' to iconcache_"
- " (" << iconcache_.size() << " icons in cache)"
+ TDEBUG_TRACEW(
+ L"GetTortoiseIcon: added '" << iconpath << L"' to iconcache_"
+ L" (" << iconcache_.size() << L" icons in cache)"
);

return h;
}


-std::string GetHgRepoRoot(const std::string& path)
+std::wstring GetHgRepoRoot(const std::wstring& path)
{
- TDEBUG_TRACE("GetHgRepoRoot('" << path << "')");
+ TDEBUG_TRACEW(L"GetHgRepoRoot('" << path << "')");

- std::string p =
+ std::wstring p =
(::PathIsUNCServerShare(path.c_str()) || IsDirectory(path))
? path : DirName(path);
for (;;)
{
- std::string tdir = p + "\\.hg";
+ std::wstring tdir = p + L"\\.hg";
if (::PathIsUNCServerShare(tdir.c_str()))
{
- TDEBUG_TRACE("GetHgRepoRoot: tdir is UNC share '" << tdir << "'");
+ TDEBUG_TRACEW(L"GetHgRepoRoot: tdir is UNC share '" << tdir << "'");
p.clear();
break;
}
else if (IsDirectory(tdir))
break;
- std::string oldp = p;
+ std::wstring oldp = p;
p = DirName(p);
if (p == oldp)
{
@@ -208,12 +185,12 @@ std::string GetHgRepoRoot(const std::str
}
}

- TDEBUG_TRACE("GetHgRepoRoot: returning '" << p << "'");
+ TDEBUG_TRACEW(L"GetHgRepoRoot: returning '" << p << "'");
return p;
}


-bool IsHgRepo(const std::string& path)
+bool IsHgRepo(const std::wstring& path)
{
return !GetHgRepoRoot(path).empty();
}
@@ -221,9 +198,9 @@ bool IsHgRepo(const std::string& path)

// open a file for reading, allowing renames and deletes by other
// processes while we have it open
-FILE* fopenReadRenameAllowed(const char* path)
+FILE* fopenReadRenameAllowed(const wchar_t* path)
{
- HANDLE fh = ::CreateFileA(
+ HANDLE fh = ::CreateFile(
path, GENERIC_READ,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0
@@ -236,7 +213,7 @@ FILE* fopenReadRenameAllowed(const char*
int fd = ::_open_osfhandle((intptr_t)fh, _O_RDONLY);
if (fd == -1)
{
- TDEBUG_TRACE("fopenReadRenameAllowed: _open_osfhandle failed");
+ TDEBUG_TRACEW(L"fopenReadRenameAllowed: _open_osfhandle failed");
::CloseHandle(fh);
return 0;
}
@@ -245,7 +222,7 @@ FILE* fopenReadRenameAllowed(const char*
FILE* f = ::_fdopen(fd, "r");
if (f == 0)
{
- TDEBUG_TRACE("fopenReadRenameAllowed: _fdopen failed");
+ TDEBUG_TRACEW(L"fopenReadRenameAllowed: _fdopen failed");
::_close(fd);
return 0;
}
@@ -253,31 +230,6 @@ FILE* fopenReadRenameAllowed(const char*
return f;
}

-
-// read string value from registry
-int GetRegSZValue(HKEY hkey, const char* name, std::string& res)
-{
- res = "";
-
- if (!hkey)
- return 0;
-
- std::vector<BYTE> Data(300);
- DWORD cbData = Data.size();
-
- LONG rv = ::RegQueryValueExA(hkey, name, 0, 0, &Data[0], &cbData);
-
- if (rv == ERROR_SUCCESS)
- {
- res = reinterpret_cast<char*>(&Data[0]);
- return 1;
- }
-
- TDEBUG_TRACE("GetRegSZValue(" << name << ") failed");
-
- return 0;
-}
-
// read string value from registry, wide version
int GetRegSZValueW(HKEY hkey, const wchar_t* name, std::wstring& res)
{
@@ -304,7 +256,7 @@ int GetRegSZValueW(HKEY hkey, const wcha


// true if a starts with b
-bool StartsWith(const std::string& a, const std::string& b)
+bool StartsWith(const std::wstring& a, const std::wstring& b)
{
if (a.empty() || b.empty())
return false;
@@ -312,7 +264,7 @@ bool StartsWith(const std::string& a, co
if (b.size() > a.size())
return false;

- for (std::string::size_type i = 0; i < b.size(); ++i)
+ for (std::wstring::size_type i = 0; i < b.size(); ++i)
{
if (a[i] != b[i])
return false;
@@ -322,10 +274,10 @@ bool StartsWith(const std::string& a, co
}


-void Tokenize(const std::string& str, std::vector<std::string>& tokens,
- const std::string& delimiters)
+void Tokenize(const std::wstring& str, std::vector<std::wstring>& tokens,
+ const std::wstring& delimiters)
{
- typedef std::string S;
+ typedef std::wstring S;
S::size_type lastpos = str.find_first_not_of(delimiters, 0);
S::size_type pos = str.find_first_of(delimiters, lastpos);

diff --git a/win32/shellext/TortoiseUtils.h b/win32/shellext/TortoiseUtils.h
--- a/win32/shellext/TortoiseUtils.h
+++ b/win32/shellext/TortoiseUtils.h
@@ -6,27 +6,20 @@
#include <string>
#include <vector>

-#define _MBSTR(wstr) hf_wctomb((LPSTR)alloca(wcslen(wstr) + 1), (wstr),wcslen(wstr) + 1)
-#define _WCSTR(str) hf_mbtowc((LPWSTR)alloca((strlen(str) + 1) * sizeof(WCHAR)),(str),strlen(str) + 1)
-
-LPWSTR hf_mbtowc(LPWSTR lpw, LPCSTR lpa, int nChars);
-LPSTR hf_wctomb(LPSTR lpa, LPCWSTR lpw, int nChars);
-
-std::string GetTHgProgRoot();
-std::string GetTemporaryFile(LPCSTR prefix="THG");
-bool IsDirectory(const std::string&);
-std::string DirName(const std::string&);
-std::string BaseName(const std::string&);
-bool LaunchCommand(const std::string& command, const std::string& cwd);
-HICON GetTortoiseIcon(const std::string & iconname);
-std::string GetHgRepoRoot(const std::string& path);
-bool IsHgRepo(const std::string& path);
-FILE* fopenReadRenameAllowed(const char* path);
-int GetRegSZValue(HKEY hkey, const char* name, std::string& res);
+std::wstring GetTHgProgRoot();
+std::wstring GetTemporaryFile(LPCWSTR prefix=L"THG");
+bool IsDirectory(const std::wstring&);
+std::wstring DirName(const std::wstring&);
+std::wstring BaseName(const std::wstring&);
+bool LaunchCommand(const std::wstring& command, const std::wstring& cwd);
+HICON GetTortoiseIcon(const std::wstring & iconname);
+std::wstring GetHgRepoRoot(const std::wstring& path);
+bool IsHgRepo(const std::wstring& path);
+FILE* fopenReadRenameAllowed(const wchar_t* path);
int GetRegSZValueW(HKEY hkey, const wchar_t* name, std::wstring& res);
-bool StartsWith(const std::string& a, const std::string& b);
-void Tokenize(const std::string& str, std::vector<std::string>& tokens,
- const std::string& delimiters = " ");
+bool StartsWith(const std::wstring& a, const std::wstring& b);
+void Tokenize(const std::wstring& str, std::vector<std::wstring>& tokens,
+ const std::wstring& delimiters = std::wstring(L" "));

template <typename C, typename T>
bool contains(const C& c, const T& t)
diff --git a/win32/shellext/Winstat.cpp b/win32/shellext/Winstat.cpp
--- a/win32/shellext/Winstat.cpp
+++ b/win32/shellext/Winstat.cpp
@@ -19,16 +19,16 @@
#include "Winstat.h"


-int Winstat::lstat(const char* file)
+int Winstat::lstat(const wchar_t* file)
{
const __int64 days_between_epochs = 134774L; /* days between 1.1.1601 and 1.1.1970 */
const __int64 secs_between_epochs = (__int64)days_between_epochs * 86400L;
const __int64 divisor = 10000000L;

- WIN32_FIND_DATAA data;
+ WIN32_FIND_DATA data;
HANDLE hfind;

- hfind = FindFirstFileA(file, &data);
+ hfind = FindFirstFile(file, &data);
if (hfind == INVALID_HANDLE_VALUE)
return -1;
FindClose(hfind);
diff --git a/win32/shellext/Winstat.h b/win32/shellext/Winstat.h
--- a/win32/shellext/Winstat.h
+++ b/win32/shellext/Winstat.h
@@ -24,7 +24,7 @@ public:
unsigned mtime;
bool isdir;

- int lstat(const char* file);
+ int lstat(const wchar_t* file);
};

#endif
diff --git a/win32/shellext/Winstat64.cpp b/win32/shellext/Winstat64.cpp
--- a/win32/shellext/Winstat64.cpp
+++ b/win32/shellext/Winstat64.cpp
@@ -18,12 +18,12 @@

#include "Winstat64.h"

-int Winstat64::lstat(const char* path)
+int Winstat64::lstat(const wchar_t* path)
{
- WIN32_FIND_DATAA data;
+ WIN32_FIND_DATA data;
HANDLE hfind;

- hfind = FindFirstFileA(path, &data);
+ hfind = FindFirstFile(path, &data);
if (hfind == INVALID_HANDLE_VALUE)
return -1;
FindClose(hfind);
diff --git a/win32/shellext/Winstat64.h b/win32/shellext/Winstat64.h
--- a/win32/shellext/Winstat64.h
+++ b/win32/shellext/Winstat64.h
@@ -21,7 +21,7 @@ struct Winstat64
{
__int64 mtime;
__int64 size;
- int lstat(const char* path);
+ int lstat(const wchar_t* path);
};

#endif
diff --git a/win32/shellext/dirstate.cpp b/win32/shellext/dirstate.cpp
--- a/win32/shellext/dirstate.cpp
+++ b/win32/shellext/dirstate.cpp
@@ -19,16 +19,19 @@

#include "dirstate.h"
#include "TortoiseUtils.h"
+#include "StringUtils.h"

-
-std::auto_ptr<Dirstate> Dirstate::read(const std::string& path, bool& unset)
+std::auto_ptr<Dirstate> Dirstate::read(
+ const std::wstring& path,
+ bool& unset
+ )
{
unset = false;

FILE *f = fopenReadRenameAllowed(path.c_str());
if (!f)
{
- TDEBUG_TRACE("Dirstate::read: can't open " << path);
+ TDEBUG_TRACEW(L"Dirstate::read: can't open " << path);
return std::auto_ptr<Dirstate>(0);
}

@@ -38,20 +41,26 @@ std::auto_ptr<Dirstate> Dirstate::read(c
fread(&pd->parent2, sizeof(char), HASH_LENGTH, f);

Direntry e;
+ // UTF-8 if fixutf8 enabled, else CP_ACP
+ // This is dynamic expansion at Direntry::read()
std::vector<char> relpath(MAX_PATH + 10, 0);
while (e.read(f, relpath))
{
if (e.unset())
+ {
unset = true;
+ }
+ if (e.state == 'a')
+ {
+ ++pd->num_added_;
+ }

- if (e.state == 'a')
- ++pd->num_added_;
-
- pd->add(&relpath[0], e);
+ std::wstring urelpath = ThgMultibyteToWide(&relpath[0]);
+ ::CharLowerBuff(&urelpath[0], urelpath.length());
+ pd->add(urelpath, e);
}

fclose(f);
-
return pd;
}

@@ -74,13 +83,13 @@ static char *revhash_string(const char r
void testread()
{
bool unset;
- std::auto_ptr<Dirstate> pd = Dirstate::read(".hg/dirstate", unset);
+ std::auto_ptr<Dirstate> pd = Dirstate::read(L".hg/dirstate", unset);
if (!pd.get()) {
printf("error: could not read .hg/dirstate\n");
return;
}
time_t t;
- char *s;
+ wchar_t *s;
unsigned ix;
printf("parent1: %s\n", revhash_string(pd->parent1));
printf("parent2: %s\n", revhash_string(pd->parent2));
diff --git a/win32/shellext/dirstate.h b/win32/shellext/dirstate.h
--- a/win32/shellext/dirstate.h
+++ b/win32/shellext/dirstate.h
@@ -36,21 +36,24 @@ public:
char parent1[HASH_LENGTH];
char parent2[HASH_LENGTH];

- static std::auto_ptr<Dirstate> read(const std::string& path, bool& unset);
+ static std::auto_ptr<Dirstate> read(
+ const std::wstring& path,
+ bool& unset
+ );

Directory& root() { return root_; }

- void add(const std::string& relpath, Direntry& e) {
+ void add(const std::wstring& relpath, Direntry& e) {
root_.add(relpath, e);
++num_entries_;
}
-
+
unsigned num_added() const { return num_added_; }
unsigned size() const { return num_entries_; }

private:
Dirstate()
- : root_(0, "", ""), num_added_(0), num_entries_(0) {}
+ : root_(0, L"", L""), num_added_(0), num_entries_(0) {}
};

#endif
diff --git a/win32/shellext/stdafx.h b/win32/shellext/stdafx.h
--- a/win32/shellext/stdafx.h
+++ b/win32/shellext/stdafx.h
@@ -32,15 +32,9 @@
#define THG_PREFIXL L"[THGx86] "
#endif

- // TDEBUG_TRACE() prints debugging messages to Windows' debugger display.
+ // TDEBUG_TRACEW() prints debugging messages to Windows' debugger display.
// The messages can be viewed with Sysinternals DebugView, which may be
// downloaded from Microsoft TechNet.
- #define TDEBUG_TRACE(s) if (ThgDebug::enabled()) { \
- std::stringstream _the_msg; \
- _the_msg << THG_PREFIX << s; \
- std::string _the_str = _the_msg.str(); \
- OutputDebugStringA(_the_str.c_str()); \
- }
#define TDEBUG_TRACEW(s) if (ThgDebug::enabled()) { \
std::basic_stringstream<wchar_t> _the_msg; \
_the_msg << THG_PREFIXL << s; \

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:05 AM7/22/11
to thg...@googlegroups.com
This is V2 of my sent mail at Tue, 19 Jul 2011 07:48:32 +0900.
http://groups.google.com/group/thg-dev/browse_thread/thread/77ba8c34e72aa8fe#

I did code clean up and rebased.

I uploaded dlls built by these patches.
* https://bitbucket.org/marutosi/tortoisehg/downloads/THgShellx86.PyQt.no-utf8.20110722.dll
* https://bitbucket.org/marutosi/tortoisehg/downloads/THgShellx64.PyQt.no-utf8.20110722.dll

Following is resending V1.

------------------------

------------------------
Added in V2.

I uploaded dlls for fixutf8 extension.
* http://bitbucket.org/marutosi/tortoisehg/downloads/THgShellx86.PyQt.20110722.dll
* http://bitbucket.org/marutosi/tortoisehg/downloads/THgShellx64.PyQt.20110722.dll

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:06 AM7/22/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311289874 -32400
# Branch stable
# Node ID c8d12e6f1e2c247e5cec3a9774fc490ccbeaf72c
# Parent 91ecbd9f547ea701940944a44a03523f8a333046
shellext: remove trailing white-spaces from CShellExtCMenu.cpp.

diff --git a/win32/shellext/CShellExtCMenu.cpp b/win32/shellext/CShellExtCMenu.cpp
--- a/win32/shellext/CShellExtCMenu.cpp
+++ b/win32/shellext/CShellExtCMenu.cpp

@@ -158,7 +158,7 @@ void GetCMenuTranslation(
else
{
TDEBUG_TRACEW(
- L"GetCMenuTranslation: RegOpenKeyExW(\""
+ L"GetCMenuTranslation: RegOpenKeyExW(\""
<< subkey << "\") failed"
);
}
@@ -192,7 +192,7 @@ void CShellExtCMenu::InitMenuMaps(const

myDescMap[md.name] = md;
}
-
+
}

myMenuIdMap.clear();
@@ -335,7 +335,7 @@ int HasTortoiseMenu(HMENU hMenu, bool& h
{
memset(&mii, 0, sizeof(MENUITEMINFOW));
mii.cbSize = sizeof(MENUITEMINFOW);
-
+
// first GetMenuItemInfoW call: get size of menu item string


mii.fMask = MIIM_STRING;
BOOL res = ::GetMenuItemInfoW(hMenu, i, true, &mii);

@@ -639,7 +639,7 @@ CShellExtCMenu::GetCommandString(

{
pszw = iter->second.helpText.c_str();
res = S_OK;
-
+


size_t size = iter->second.helpText.size();
if (size >= 40)
{

@@ -896,7 +896,7 @@ void CShellExtCMenu::PrintDebugHeader(LP
}

TDEBUG_TRACEW(
- L"---- TortoiseHg shell extension version "
+ L"---- TortoiseHg shell extension version "


<< ThgVersion::get() << L"----"
);

@@ -921,7 +921,7 @@ STDMETHODIMP CShellExtCMenu::Initialize(


if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)) && stg.hGlobal)

{
HDROP hDrop = (HDROP) GlobalLock(stg.hGlobal);

-
+


if (hDrop)
{
UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);

@@ -931,10 +931,10 @@ STDMETHODIMP CShellExtCMenu::Initialize(
{


TDEBUG_TRACE(" DragQueryFile [" << i << "] = " << name);

myFiles.push_back(name);
- }
+ }
}
}
- else
+ else
{


TDEBUG_TRACE(" hDrop is NULL ");
}

@@ -953,7 +953,7 @@ STDMETHODIMP CShellExtCMenu::Initialize(


}

// if a directory background

- if (pIDFolder)
+ if (pIDFolder)
{
SHGetPathFromIDList(pIDFolder, name);
TDEBUG_TRACE(" Folder " << name);

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:07 AM7/22/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311290619 -32400
# Branch stable
# Node ID 6dfcdd3fde81d58bc3a72170984af7fca918f46c
# Parent c8d12e6f1e2c247e5cec3a9774fc490ccbeaf72c
shellext: remove trailing white-spaces from Directory.cpp.

diff --git a/win32/shellext/Directory.cpp b/win32/shellext/Directory.cpp
--- a/win32/shellext/Directory.cpp
+++ b/win32/shellext/Directory.cpp

@@ -73,10 +73,10 @@ int Directory::add(const std::string& n_
{
std::string base;
std::string rest;
-
+


std::string n = n_in;

Directory* cur = this;
-
+
for (;;)
{

@@ -94,7 +94,7 @@ int Directory::add(const std::string& n_
}

Directory* d = 0;
- for (DirsT::iterator i = cur->subdirs_.begin();
+ for (DirsT::iterator i = cur->subdirs_.begin();


i != cur->subdirs_.end(); ++i)

{
if ((*i)->name_ == base) {

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:08 AM7/22/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311293101 -32400
# Branch stable
# Node ID 5667137d6d01ade6f99cd93c13fdeb742be710dc
# Parent 6dfcdd3fde81d58bc3a72170984af7fca918f46c
shellext: remove trailing white-spaces from QueryDirstate.cpp.

diff --git a/win32/shellext/QueryDirstate.cpp b/win32/shellext/QueryDirstate.cpp
--- a/win32/shellext/QueryDirstate.cpp
+++ b/win32/shellext/QueryDirstate.cpp

@@ -78,12 +78,12 @@ bool hasHgDir(char cls, const std::strin



int findHgRoot(char cls, QueryState& cur, QueryState& last, bool outdated)

{
- std::string dp = "["; dp += cls; dp += "] findHgRoot";

+ std::string dp = "["; dp += cls; dp += "] findHgRoot";

{


std::string p = cur.path;

p.push_back('\\');
- if (p.find("\\.hg\\") != std::string::npos)

+ if (p.find("\\.hg\\") != std::string::npos)


{
// ignore files and dirs named '.hg'
last = cur;

@@ -91,7 +91,7 @@ int findHgRoot(char cls, QueryState& cur


}
}

- if (!outdated && !last.hgroot.empty()
+ if (!outdated && !last.hgroot.empty()
&& cur.path.size() >= last.hgroot.size()

&& StartsWith(cur.path, last.hgroot + "\\"))

{
@@ -141,7 +141,7 @@ int findHgRoot(char cls, QueryState& cur


goto exit;
}

- if (has_hg)
+ if (has_hg)
{
cur.hgroot = p;

TDEBUG_TRACE(
@@ -173,7 +173,7 @@ exit:




int get_relpath(
- const std::string& hgroot,

+ const std::string& hgroot,
const std::string& path,
std::string& res
)
@@ -187,7 +187,7 @@ int get_relpath(



if (path[offset] == '\\')

offset++;
-
+


const char* relpathptr = path.c_str() + offset;

res = relpathptr;
@@ -198,11 +198,11 @@ int get_relpath(


int HgQueryDirstate(
const char cls,

const std::string& path,
- const char& filterStatus,

+ const char& filterStatus,


char& outStatus
)
{
- std::string dp = "["; dp += cls; dp += "] HgQueryDirstate: ";

+ std::string dp = "["; dp += cls; dp += "] HgQueryDirstate: ";

static QueryState last;

@@ -216,7 +216,7 @@ int HgQueryDirstate(



const bool outdated = cur.tickcount - last.tickcount > 2000;

- if (!outdated && last.path == path)
+ if (!outdated && last.path == path)
{
outStatus = last.status;
if (outStatus == 'P')

@@ -283,7 +283,7 @@ int HgQueryDirstate(


}

Winstat stat;
- if (0 != stat.lstat(path.c_str()))
+ if (0 != stat.lstat(path.c_str()))
{

TDEBUG_TRACE(dp << "lstat(" << path << ") failed");

last = cur;
@@ -313,7 +313,7 @@ int HgQueryDirstate(


}

const Direntry* const e = pds->root().get(relpath);
- if (!e)
+ if (!e)
{
last = cur;
return 0;

@@ -338,7 +338,7 @@ int HgQueryDirstate(

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:09 AM7/22/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311293101 -32400
# Branch stable
# Node ID f301b3ddf7df41ba29a787dc737b12df67f91c65
# Parent 5667137d6d01ade6f99cd93c13fdeb742be710dc
shellext: remove trailing white-spaces from Dirstatecache.h.

diff --git a/win32/shellext/Dirstatecache.h b/win32/shellext/Dirstatecache.h
--- a/win32/shellext/Dirstatecache.h
+++ b/win32/shellext/Dirstatecache.h

@@ -35,13 +35,13 @@ class Dirstatecache

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:10 AM7/22/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311323975 -32400
# Branch stable
# Node ID d8bca2e5dbc7fec9f8b0137f7dc52865fba0f8a7
# Parent f301b3ddf7df41ba29a787dc737b12df67f91c65
shellext: remove trailing white-spaces from Dirstatecache.cpp.

diff --git a/win32/shellext/Dirstatecache.cpp b/win32/shellext/Dirstatecache.cpp
--- a/win32/shellext/Dirstatecache.cpp
+++ b/win32/shellext/Dirstatecache.cpp

@@ -92,10 +92,10 @@ Dirstate* Dirstatecache::get(


new_stat = true;
}

- if (iter->dstate)
+ if (iter->dstate)
{
unset = iter->unset;
-

+
if (!new_stat)
return iter->dstate;

@@ -106,8 +106,8 @@ Dirstate* Dirstatecache::get(


}

TDEBUG_TRACE("Dirstatecache::get: refreshing " << hgroot);
- }
- else
+ }

+ else
{

Toshi MARUYAMA

unread,
Jul 22, 2011, 10:45:11 AM7/22/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311123270 -32400
# Branch stable
# Node ID f25f57744831a0970f957c1744e0134bd79dabd7
# Parent d8bca2e5dbc7fec9f8b0137f7dc52865fba0f8a7

shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)

Issue https://bitbucket.org/tortoisehg/stable/issue/1241

Merge squashed following jobs.
* Marco Lizza's patches exclude tortoisehg_rev6547.patch (Msi.lib).
http://groups.google.com/group/thg-dev/browse_thread/thread/8580c791fe5b52b2
* Tinyfish's Unicode porting.
http://bitbucket.org/tinyfish/tortoisehg.winutf8/changeset/cdce65b00f1e

diff --git a/win32/shellext/CShellExtCMenu.cpp b/win32/shellext/CShellExtCMenu.cpp
--- a/win32/shellext/CShellExtCMenu.cpp
+++ b/win32/shellext/CShellExtCMenu.cpp

@@ -340,7 +348,7 @@ int HasTortoiseMenu(HMENU hMenu, bool& h


mii.fMask = MIIM_STRING;
BOOL res = ::GetMenuItemInfoW(hMenu, i, true, &mii);

if (res == 0) {
- TDEBUG_TRACE("HasTortoiseMenu: "
+ TDEBUG_TRACEW(L"HasTortoiseMenu: "
<< "first GetMenuItemInfo returned 0");
continue;
}
@@ -359,7 +367,7 @@ int HasTortoiseMenu(HMENU hMenu, bool& h
++mii.cch; // size of buffer is one more than length of string

res = ::GetMenuItemInfoW(hMenu, i, true, &mii);

size_t size = iter->second.helpText.size();
if (size >= 40)
{

- TDEBUG_TRACE(
- "***** CShellExtCMenu::GetCommandString: warning:"
- << " length of help text is " << size
- << ", which is not reasonably short (<40)");
+ TDEBUG_TRACEW(
+ L"***** CShellExtCMenu::GetCommandString: warning:"
+ << L" length of help text is " << size
+ << L", which is not reasonably short (<40)");
}
}
else if (uFlags == GCS_HELPTEXTA)
@@ -673,7 +737,7 @@ CShellExtCMenu::GetCommandString(

if (cchMax < 1)
{
- TDEBUG_TRACE("CShellExtCMenu::GetCommandString: cchMax = "
+ TDEBUG_TRACEW(L"CShellExtCMenu::GetCommandString: cchMax = "
<< cchMax << " (is <1)");
return res;
}

@@ -683,7 +747,8 @@ CShellExtCMenu::GetCommandString(

<< ThgVersion::get() << L"----"
);

- TDEBUG_TRACE(" pIDFolder: " << pIDFolder);
- TDEBUG_TRACE(" pDataObj: " << pDataObj);
+ TDEBUG_TRACEW(L" pIDFolder: " << pIDFolder);
+ TDEBUG_TRACEW(L" pDataObj: " << pDataObj);
}

STDMETHODIMP CShellExtCMenu::Initialize(
@@ -918,56 +1020,54 @@ STDMETHODIMP CShellExtCMenu::Initialize(
{
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
- if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)) && stg.hGlobal)
+ if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)))
{

HDROP hDrop = (HDROP) GlobalLock(stg.hGlobal);

if (hDrop)
{
UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);

- TDEBUG_TRACE(" hDrop uNumFiles = " << uNumFiles);
+ TDEBUG_TRACEW(L" hDrop uNumFiles = " << uNumFiles);
for (UINT i = 0; i < uNumFiles; ++i) {
if (DragQueryFile(hDrop, i, name, MAX_PATH) > 0)
{

- TDEBUG_TRACE(" DragQueryFile [" << i << "] = " << name);
+ TDEBUG_TRACEW(L" DragQueryFile [" << i << "] = " << name);
myFiles.push_back(name);
}
}
}
- else


- {
- TDEBUG_TRACE(" hDrop is NULL ");
- }

GlobalUnlock(stg.hGlobal);
- if (stg.pUnkForRelease)
+ ReleaseStgMedium(&stg);
+
+ if (hDrop == NULL)
{
- IUnknown* relInterface = (IUnknown*) stg.pUnkForRelease;
- relInterface->Release();
+ TDEBUG_TRACEW(L" hDrop is NULL ");
+ return E_INVALIDARG;
}
}
else
{
- TDEBUG_TRACE(" pDataObj->GetData failed");
+ TDEBUG_TRACEW(L" pDataObj->GetData failed");
+ return E_INVALIDARG;
}
}

// if a directory background

if (hDrop)
{
UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);

- TDEBUG_TRACE(" hDrop uNumFiles = " << uNumFiles);
+ TDEBUG_TRACEW(L" hDrop uNumFiles = " << uNumFiles);
for (UINT i = 0; i < uNumFiles; ++i) {
if (DragQueryFile(hDrop, i, name, MAX_PATH) > 0)
{

diff --git a/win32/shellext/Directory.cpp b/win32/shellext/Directory.cpp
--- a/win32/shellext/Directory.cpp
+++ b/win32/shellext/Directory.cpp

@@ -24,7 +24,7 @@

- std::string n = n_in;
+ std::wstring n = n_in;
Directory* cur = this;

for (DirsT::const_iterator i = cur->subdirs_.begin();


i != cur->subdirs_.end(); ++i)

diff --git a/win32/shellext/Dirstatecache.cpp b/win32/shellext/Dirstatecache.cpp
--- a/win32/shellext/Dirstatecache.cpp
+++ b/win32/shellext/Dirstatecache.cpp

@@ -80,36 +83,35 @@ Dirstate* Dirstatecache::get(


{
if (0 != stat.lstat(path.c_str()))
{
- TDEBUG_TRACE("Dirstatecache::get: lstat(" << path <<") failed");
- TDEBUG_TRACE("Dirstatecache::get: dropping " << iter->hgroot);
+ TDEBUG_TRACEW(L"Dirstatecache::get: lstat(" << path <<") failed");
+ TDEBUG_TRACEW(L"Dirstatecache::get: dropping " << iter->hgroot);
delete iter->dstate;
iter->dstate = 0;
cache().erase(iter);
return 0;
}
iter->tickcount = tc;
- TDEBUG_TRACE("Dirstatecache::get: lstat(" << path <<") ok ");
+ TDEBUG_TRACEW(L"Dirstatecache::get: lstat(" << path <<") ok ");
new_stat = true;
}

if (iter->dstate)
{
unset = iter->unset;
-

if (!new_stat)
+ {
return iter->dstate;
-
+ }
if (iter->dstate_mtime == stat.mtime
&& iter->dstate_size == stat.size)
{
return iter->dstate;
}
-

- TDEBUG_TRACE("Dirstatecache::get: refreshing " << hgroot);


+ TDEBUG_TRACEW(L"Dirstatecache::get: refreshing " << hgroot);
}

else
{
- TDEBUG_TRACE("Dirstatecache::get: reading " << hgroot);
+ TDEBUG_TRACEW(L"Dirstatecache::get: reading " << hgroot);
}

unset = false;

@@ -123,13 +125,13 @@ Dirstate* Dirstatecache::get(


{
if (iter->unset)
{
- TDEBUG_TRACE(
- "Dirstatecache::get: **** old and new have unset entries");
+ TDEBUG_TRACEW(
+ L"Dirstatecache::get: **** old and new have unset entries");
request_thgstatus_update = false;
}
else
{
- TDEBUG_TRACE("Dirstatecache::get: new has unset entries");
+ TDEBUG_TRACEW(L"Dirstatecache::get: new has unset entries");
}
}

@@ -139,7 +141,7 @@ Dirstate* Dirstatecache::get(


iter->dstate = ds.release();

unsigned delta = tc1 - tc0;
- TDEBUG_TRACE("Dirstatecache::get: read done in " << delta << " ticks, "
+ TDEBUG_TRACEW(L"Dirstatecache::get: read done in " << delta << " ticks, "
<< cache().size() << " repos in cache");

iter->dstate_mtime = stat.mtime;

@@ -147,25 +149,26 @@ Dirstate* Dirstatecache::get(



if (request_thgstatus_update)
{
- TDEBUG_TRACE("Dirstatecache::get: calling Thgstatus::update");
+ TDEBUG_TRACEW(L"Dirstatecache::get: calling Thgstatus::update");
Thgstatus::update(cwd);
}
else
{
- TDEBUG_TRACE("Dirstatecache::get: omitting Thgstatus::update");
+ TDEBUG_TRACEW(L"Dirstatecache::get: omitting Thgstatus::update");
}

return iter->dstate;
}


-void Dirstatecache::invalidate(const std::string& hgroot)
+void Dirstatecache::invalidate(const std::wstring& hgroot)
{
typedef std::list<E>::iterator Iter;

if (hgroot.empty())
+ {
return;
-
+ }
for (Iter i = cache().begin(); i != cache().end(); ++i)
{
if (hgroot == i->hgroot)

@@ -173,7 +176,7 @@ void Dirstatecache::invalidate(const std


delete i->dstate;
i->dstate = 0;
cache().erase(i);
- TDEBUG_TRACE("Dirstatecache::invalidate(" << hgroot << ")");
+ TDEBUG_TRACEW(L"Dirstatecache::invalidate(" << hgroot << ")");
break;
}
}

diff --git a/win32/shellext/Dirstatecache.h b/win32/shellext/Dirstatecache.h
--- a/win32/shellext/Dirstatecache.h
+++ b/win32/shellext/Dirstatecache.h

@@ -31,7 +31,7 @@ class Dirstatecache


__int64 dstate_mtime;
__int64 dstate_size;

- std::string hgroot;
+ std::wstring hgroot;
unsigned tickcount;
bool unset;

@@ -48,8 +48,11 @@ class Dirstatecache

diff --git a/win32/shellext/QueryDirstate.cpp b/win32/shellext/QueryDirstate.cpp
--- a/win32/shellext/QueryDirstate.cpp
+++ b/win32/shellext/QueryDirstate.cpp

@@ -76,14 +75,14 @@ bool hasHgDir(char cls, const std::strin
}


-int findHgRoot(char cls, QueryState& cur, QueryState& last, bool outdated)
+int findHgRoot(wchar_t cls, QueryState& cur, QueryState& last, bool outdated)


{
- std::string dp = "["; dp += cls; dp += "] findHgRoot";

+ std::wstring dp = L"["; dp += cls; dp += L"] findHgRoot";

{
- std::string p = cur.path;
- p.push_back('\\');


- if (p.find("\\.hg\\") != std::string::npos)

+ std::wstring p = cur.path;
+ p.push_back(L'\\');

+ if (p.find(L"\\.hg\\") != std::wstring::npos)


{
// ignore files and dirs named '.hg'
last = cur;

@@ -93,7 +92,7 @@ int findHgRoot(char cls, QueryState& cur



if (!outdated && !last.hgroot.empty()
&& cur.path.size() >= last.hgroot.size()

- && StartsWith(cur.path, last.hgroot + "\\"))
+ && StartsWith(cur.path, last.hgroot + L"\\"))
{
cur.hgroot = last.hgroot;
return 1;
@@ -117,7 +116,7 @@ int findHgRoot(char cls, QueryState& cur
if (has_hg)
{
cur.hgroot = cur.path;
- TDEBUG_TRACE(dp << "(" << cur.path << "): hgroot = cur.path");
+ TDEBUG_TRACEW(dp << L"(" << cur.path << L"): hgroot = cur.path");
return 1;
}
}

@@ -130,12 +129,12 @@ int findHgRoot(char cls, QueryState& cur


return 1;
}

- for (std::string p = cur.basedir;;)
+ for (std::wstring p = cur.basedir;;)
{
bool has_hg = hasHgDir(cls, p, ticks);
if (ticks > 5000 /* ms */)
{
- const std::string reason = "ignoring slow \"" + p + "\"";
+ const std::wstring reason = L"ignoring slow \"" + p + L"\"";
Thgstatus::error(reason);
file_access_is_unacceptably_slow = true;
goto exit;

@@ -144,13 +143,13 @@ int findHgRoot(char cls, QueryState& cur


if (has_hg)
{
cur.hgroot = p;

last = cur;
return 0;

@@ -173,9 +172,9 @@ exit:




int get_relpath(
- const std::string& hgroot,

- const std::string& path,
- std::string& res
+ const std::wstring& hgroot,
+ const std::wstring& path,
+ std::wstring& res
)
{
size_t offset = hgroot.size();
@@ -185,24 +184,23 @@ int get_relpath(
if (offset > path.size())
return 0;

- if (path[offset] == '\\')
+ if (path[offset] == L'\\')
offset++;

- const char* relpathptr = path.c_str() + offset;
+ const wchar_t* relpathptr = path.c_str() + offset;

res = relpathptr;
return 1;
}

-


int HgQueryDirstate(
const char cls,

- const std::string& path,
- const char& filterStatus,


+ const std::wstring& path,

+ const wchar_t& filterStatus,


char& outStatus
)
{
- std::string dp = "["; dp += cls; dp += "] HgQueryDirstate: ";

+ std::wstring dp = L"["; dp += cls; dp += L"] HgQueryDirstate: ";

static QueryState last;


@@ -241,19 +239,21 @@ int HgQueryDirstate(
return 0;
}

- if (path[offset] == '\\')
+ if (path[offset] == L'\\')
offset++;

- const char* relpathptr = path.c_str() + offset;
+ const wchar_t* relpathptr = path.c_str() + offset;

- std::string relpath = relpathptr;
+ std::wstring relpath = relpathptr;

for (size_t i = 0; i < relpath.size(); ++i)
{
- if (relpath[i] == '\\')
- relpath[i] = '/';
+ if (relpath[i] == L'\\')
+ relpath[i] = L'/';
}

- DirectoryStatus* pdirsta = DirectoryStatus::get(cur.hgroot, cur.basedir);
+ // read .hg/thgstatus
+ DirectoryStatus* pdirsta = DirectoryStatus::get(
+ cur.hgroot, cur.basedir);
if (pdirsta && pdirsta->noicons())
{
last = cur;

@@ -271,12 +271,13 @@ int HgQueryDirstate(



bool unset = false;

+ // read .hg/dirstate
Dirstate* pds = Dirstatecache::get(cur.hgroot, cur.basedir, unset);
if (!pds)
{
- TDEBUG_TRACE(
- dp << "Dirstatecache::get(" << cur.hgroot
- << ") returns no Dirstate"
+ TDEBUG_TRACEW(
+ dp << L"Dirstatecache::get(" << cur.hgroot
+ << L") returns no Dirstate"
);

last = cur;
return 0;

@@ -285,7 +286,7 @@ int HgQueryDirstate(
Winstat stat;
if (0 != stat.lstat(path.c_str()))
{


- TDEBUG_TRACE(dp << "lstat(" << path << ") failed");

+ TDEBUG_TRACEW(dp << L"lstat(" << path << L") failed");
last = cur;
return 0;
}
@@ -328,13 +329,13 @@ int HgQueryDirstate(



if (outStatus == 'M')
{
- std::string relbase;
+ std::wstring relbase;
if (pdirsta && get_relpath(cur.hgroot, cur.basedir, relbase))
{
- TDEBUG_TRACE(dp << "relbase = '" << relbase << "'");
+ TDEBUG_TRACEW(dp << L"relbase = '" << relbase << L"'");

char basedir_status = pdirsta->status(relbase);
- TDEBUG_TRACE(dp << "basedir_status = " << basedir_status);
+ TDEBUG_TRACEW(dp << L"basedir_status = " << basedir_status);

if (basedir_status != 'M')
update = true;

@@ -353,12 +354,12 @@ int HgQueryDirstate(
lasttickcount = tc;
}

- TDEBUG_TRACE(dp << "outStatus is 'P'");
+ TDEBUG_TRACEW(dp << L"outStatus is 'P'");
}

if (update)
{
- TDEBUG_TRACE(dp << "calling Thgstatus::update");
+ TDEBUG_TRACEW(dp << L"calling Thgstatus::update");
Thgstatus::update(path);
}

diff --git a/win32/shellext/QueryDirstate.h b/win32/shellext/QueryDirstate.h
--- a/win32/shellext/QueryDirstate.h
+++ b/win32/shellext/QueryDirstate.h
@@ -5,8 +5,8 @@

int HgQueryDirstate(
const char myClass,

- const std::string& path,
- const char& filterStatus,

@@ -50,13 +52,15 @@ std::string WideToMultibyte(const std::w




// Convert multibyte string to Unicode string

-std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage)

@@ -11,8 +11,8 @@



bool ThgDebug::regDebugShellExt()
{
- std::string val;
- return GetRegistryConfig("DebugShellExt", val) != 0 && val == "1";
+ std::wstring val;
+ return GetRegistryConfig(L"DebugShellExt", val) != 0 && val == L"1";
}

bool ThgDebug::enabled()

+ STARTUPINFOW startupInfo;


memset(&startupInfo, 0, sizeof(startupInfo));

- int res = CreateProcessA(

+ int res = CreateProcessW(

+ HANDLE fh = ::CreateFileW(

+ WIN32_FIND_DATAW data;


HANDLE hfind;

- hfind = FindFirstFileA(file, &data);

+ hfind = FindFirstFileW(file, &data);


if (hfind == INVALID_HANDLE_VALUE)
return -1;
FindClose(hfind);
diff --git a/win32/shellext/Winstat.h b/win32/shellext/Winstat.h
--- a/win32/shellext/Winstat.h
+++ b/win32/shellext/Winstat.h
@@ -24,7 +24,7 @@ public:
unsigned mtime;
bool isdir;

- int lstat(const char* file);
+ int lstat(const wchar_t* file);
};

#endif
diff --git a/win32/shellext/Winstat64.cpp b/win32/shellext/Winstat64.cpp
--- a/win32/shellext/Winstat64.cpp
+++ b/win32/shellext/Winstat64.cpp
@@ -18,12 +18,12 @@

#include "Winstat64.h"

-int Winstat64::lstat(const char* path)
+int Winstat64::lstat(const wchar_t* path)
{
- WIN32_FIND_DATAA data;

+ WIN32_FIND_DATAW data;


HANDLE hfind;

- hfind = FindFirstFileA(path, &data);

+ hfind = FindFirstFileW(path, &data);

Adrian Buehlmann

unread,
Jul 22, 2011, 2:17:23 PM7/22/11
to thg...@googlegroups.com, Toshi MARUYAMA
On 2011-07-22 16:45, Toshi MARUYAMA wrote:
> # HG changeset patch
> # User Toshi MARUYAMA <marut...@gmail.com>
> # Date 1311323975 -32400
> # Branch stable
> # Node ID d8bca2e5dbc7fec9f8b0137f7dc52865fba0f8a7
> # Parent f301b3ddf7df41ba29a787dc737b12df67f91c65
> shellext: remove trailing white-spaces from Dirstatecache.cpp.

I pushed patches 1..5

Adrian Buehlmann

unread,
Jul 22, 2011, 6:03:49 PM7/22/11
to thg...@googlegroups.com, Toshi MARUYAMA
On 2011-07-22 16:45, Toshi MARUYAMA wrote:
> # HG changeset patch
> # User Toshi MARUYAMA <marut...@gmail.com>
> # Date 1311123270 -32400
> # Branch stable

Not sure this is good idea for stable. This change is too big for stable.

> # Node ID f25f57744831a0970f957c1744e0134bd79dabd7
> # Parent d8bca2e5dbc7fec9f8b0137f7dc52865fba0f8a7
> shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)

Tough patch.

Looks like you don't give up :-)

> diff --git a/win32/shellext/StringUtils.cpp b/win32/shellext/StringUtils.cpp
> --- a/win32/shellext/StringUtils.cpp
> +++ b/win32/shellext/StringUtils.cpp

..

> @@ -67,3 +71,22 @@ std::wstring MultibyteToWide(const std::
>
> return &wide[0];
> }
> +
> +// Convert multibyte string to Unicode string of .hg/dirstate and .hg/thgstatus

I don't understand what "Unicode string of .hg/dirstate" means. Contents
of .hg/dirstate are not in unicode.

If a comment is confusing like that it's probably better to not write a
comment at all...

> +std::wstring ThgMultibyteToWide (
> + const std::string& multibyte,
> + UINT CodePage
> + )
> +{
> + std::wstring wc = L"";
> + if (wc == L"")

This looks strange. Why do you test for emptyness again, right after
having assigned the empty string just before?

Toshi MARUYAMA

unread,
Jul 23, 2011, 3:45:37 AM7/23/11
to thg...@googlegroups.com
Adrian Buehlmann wrote (2011/07/23 7:03):
> On 2011-07-22 16:45, Toshi MARUYAMA wrote:
>> # HG changeset patch
>> # User Toshi MARUYAMA<marut...@gmail.com>
>> # Date 1311123270 -32400
>> # Branch stable
>
> Not sure this is good idea for stable. This change is too big for stable.

I will send V3 patch for default branch.

>
>> # Node ID f25f57744831a0970f957c1744e0134bd79dabd7
>> # Parent d8bca2e5dbc7fec9f8b0137f7dc52865fba0f8a7
>> shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)
>
> Tough patch.
>
> Looks like you don't give up :-)
>
>> diff --git a/win32/shellext/StringUtils.cpp b/win32/shellext/StringUtils.cpp
>> --- a/win32/shellext/StringUtils.cpp
>> +++ b/win32/shellext/StringUtils.cpp
>
> ..
>
>> @@ -67,3 +71,22 @@ std::wstring MultibyteToWide(const std::
>>

>> return&wide[0];


>> }
>> +
>> +// Convert multibyte string to Unicode string of .hg/dirstate and .hg/thgstatus
>
> I don't understand what "Unicode string of .hg/dirstate" means. Contents
> of .hg/dirstate are not in unicode.
>
> If a comment is confusing like that it's probably better to not write a
> comment at all...
>
>> +std::wstring ThgMultibyteToWide (
>> + const std::string& multibyte,
>> + UINT CodePage
>> + )
>> +{
>> + std::wstring wc = L"";
>> + if (wc == L"")
>
> This looks strange. Why do you test for emptyness again, right after
> having assigned the empty string just before?
>

I forgot dropping fixutf8 support completely at StringUtils.cpp.
.hg/dirstate encoding is ANSI(CP1252/ISO-8859-1, CP932/Shift-jis) on Windows.
So,"ThgMultibyteToWide()" is not needed.
I will send V3 patch that removes it.

Toshi MARUYAMA

unread,
Jul 23, 2011, 3:46:44 AM7/23/11
to thg...@googlegroups.com
# HG changeset patch
# User Toshi MARUYAMA <marut...@gmail.com>
# Date 1311123270 -32400
# Node ID ae8d01da8b125bd80beb75917b068b4064e83224
# Parent 2467e1cb55cbee21842f606d4bc9d37de85db08c

shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)

Issue https://bitbucket.org/tortoisehg/stable/issue/1241

+ std::wstring ws_src = MultibyteToWide(psz);

@@ -56,18 +56,19 @@ char DirectoryStatus::status(const std::


}


-int DirectoryStatus::read(const std::string& hgroot, const std::string& cwd)
+int DirectoryStatus::read(
+ const std::wstring& hgroot,
+ const std::wstring& cwd
+ )
{

v_.clear();
noicons_ = false;
-
- std::string p = hgroot + "\\.hg\\thgstatus";

-


+ std::wstring p = hgroot + L"\\.hg\\thgstatus";
FILE *f = fopenReadRenameAllowed(p.c_str());
if (!f)
{
- TDEBUG_TRACE("DirectoryStatus::read: can't open '" << p << "'");
- std::string p = (cwd.size() < hgroot.size() ? hgroot : cwd);
+ TDEBUG_TRACEW(L"DirectoryStatus::read: can't open '" << p << L"'");
+ std::wstring p = (cwd.size() < hgroot.size() ? hgroot : cwd);
Thgstatus::update(p);
return 0;
}

@@ -112,23 +113,23 @@ int DirectoryStatus::read(const std::str



e.status_ = line[0];

- std::string path;
+ std::string path;
+ std::wstring wpath;
if (line.size() > 1)
{
path = line.c_str() + 1;
- ::CharLower(const_cast<char*>(path.c_str()));

+ wpath = MultibyteToWide(path);


+ ::CharLower(const_cast<wchar_t*>(wpath.c_str()));
}
- path.push_back('/');
-
- e.path_ = path;
-
+ wpath.push_back(L'/');
+ e.path_ = wpath;
v_.push_back(e);
}

close:
fclose(f);

- TDEBUG_TRACE("DirectoryStatus::read(" << hgroot << "): done. "
+ TDEBUG_TRACEW(L"DirectoryStatus::read(" << hgroot << "): done. "
<< v_.size() << " entries read. noicons_ = " << noicons_ );

return res;

@@ -137,7 +138,7 @@ close:



struct CacheEntry
{
- std::string hgroot_;
+ std::wstring hgroot_;
DirectoryStatus ds_;
bool readfailed_;
unsigned tickcount_;

@@ -147,10 +148,11 @@ struct CacheEntry




DirectoryStatus* DirectoryStatus::get(
- const std::string& hgroot, const std::string& cwd)
+ const std::wstring& hgroot,
+ const std::wstring& cwd
+ )
{
static CacheEntry ce;
-
unsigned tc = GetTickCount();

if (ce.hgroot_ != hgroot || (tc - ce.tickcount_) > 2000)

@@ -163,5 +165,3 @@ DirectoryStatus* DirectoryStatus::get(

diff --git a/win32/shellext/StringUtils.cpp b/win32/shellext/StringUtils.cpp
--- a/win32/shellext/StringUtils.cpp
+++ b/win32/shellext/StringUtils.cpp

@@ -19,11 +19,10 @@

#include <vector>

-


// Quotes a string
-std::string Quote(const std::string& str)
+std::wstring Quote(const std::wstring& str)
{
- std::string sResult = "\"" + str + "\"";
+ std::wstring sResult = L"\"" + str + L"\"";
return sResult;
}

@@ -36,15 +35,12 @@ std::string WideToMultibyte(const std::w
CodePage, 0, wide.c_str(), static_cast<int>(wide.length()),
NULL, 0, NULL, NULL
);
-
std::vector<CHAR> narrow(ret + 1);
-
ret = WideCharToMultiByte(
CodePage, 0, wide.c_str(), static_cast<int>(wide.length()),
&narrow[0], ret, NULL, NULL
);
narrow[ret] = '\0';
-
return &narrow[0];
}

@@ -56,14 +52,11 @@ std::wstring MultibyteToWide(const std::
CodePage, 0, multibyte.c_str(),


static_cast<int>(multibyte.length()), 0, 0
);

-


std::vector<wchar_t> wide(ret + 1);

-
ret = MultiByteToWideChar(
CodePage, 0, multibyte.c_str(),
static_cast<int>(multibyte.length()), &wide[0], ret
);
wide[ret] = L'\0';
-
return &wide[0];


}
diff --git a/win32/shellext/StringUtils.h b/win32/shellext/StringUtils.h
--- a/win32/shellext/StringUtils.h
+++ b/win32/shellext/StringUtils.h

@@ -22,7 +22,7 @@


#include <windows.h>

// Quotes a string
-std::string Quote(const std::string& str);
+std::wstring Quote(const std::wstring& str);

// Convert Unicode string to multibyte string
std::string WideToMultibyte(const std::wstring& wide, UINT CodePage = CP_ACP);

@@ -30,5 +30,4 @@ std::string WideToMultibyte(const std::w


// Convert multibyte string to Unicode string

std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage = CP_ACP);

-

@@ -38,20 +41,23 @@ std::auto_ptr<Dirstate> Dirstate::read(c


fread(&pd->parent2, sizeof(char), HASH_LENGTH, f);

Direntry e;

+ // This is dynamic expansion at Direntry::read()
std::vector<char> relpath(MAX_PATH + 10, 0);
while (e.read(f, relpath))
{
if (e.unset())
+ {
unset = true;

-


+ }
if (e.state == 'a')
+ {

++pd->num_added_;
-
- pd->add(&relpath[0], e);
+ }

+ std::wstring urelpath = MultibyteToWide(&relpath[0]);


+ ::CharLowerBuff(&urelpath[0], urelpath.length());
+ pd->add(urelpath, e);
}

-
fclose(f);
-
return pd;
}

@@ -74,13 +80,13 @@ static char *revhash_string(const char r

Adrian Buehlmann

unread,
Jul 25, 2011, 5:36:24 AM7/25/11
to thg...@googlegroups.com, Toshi MARUYAMA
On 2011-07-23 09:46, Toshi MARUYAMA wrote:
> # HG changeset patch
> # User Toshi MARUYAMA <marut...@gmail.com>
> # Date 1311123270 -32400
> # Node ID ae8d01da8b125bd80beb75917b068b4064e83224
> # Parent 2467e1cb55cbee21842f606d4bc9d37de85db08c
> shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)

Could this patch be splitted into multiple smaller ones? This patch is
very big and it is very hard to review.

Ideally, we try to do small patches one after one, each patch doing a
small, focused (but still self consistent) change at a time.

Would it be possible to first do the context-menu disabling thing in a
separate first patch alone?

I think we are often more lenient about patches on the TortoiseHg
project compared to the Mercurial project itself, but observing
http://mercurial.selenic.com/wiki/ContributingChanges#Organizing_patches
can still be helpful.

(please scroll down to the end, I wrote another comment at the end)

> Issue https://bitbucket.org/tortoisehg/stable/issue/1241
>
> Merge squashed following jobs.
> * Marco Lizza's patches exclude tortoisehg_rev6547.patch (Msi.lib).
> http://groups.google.com/group/thg-dev/browse_thread/thread/8580c791fe5b52b2
> * Tinyfish's Unicode porting.
> http://bitbucket.org/tinyfish/tortoisehg.winutf8/changeset/cdce65b00f1e
>
> diff --git a/win32/shellext/CShellExtCMenu.cpp b/win32/shellext/CShellExtCMenu.cpp
> --- a/win32/shellext/CShellExtCMenu.cpp
> +++ b/win32/shellext/CShellExtCMenu.cpp

..

I do not understand this "if ( ! root.empty() )" part. Why are you doing
this?

If it is needed, could you do this in a separate patch (before doing the
big unicode change)?

Toshi MARUYAMA

unread,
Jul 25, 2011, 8:26:51 AM7/25/11
to thg...@googlegroups.com
Adrian Buehlmann wrote (2011/07/25 18:36):
> On 2011-07-23 09:46, Toshi MARUYAMA wrote:
>> # HG changeset patch
>> # User Toshi MARUYAMA<marut...@gmail.com>
>> # Date 1311123270 -32400
>> # Node ID ae8d01da8b125bd80beb75917b068b4064e83224
>> # Parent 2467e1cb55cbee21842f606d4bc9d37de85db08c
>> shellext: Unicode porting and context-menu disabled on special folders (e.g. start-menu)
>
> Could this patch be splitted into multiple smaller ones? This patch is
> very big and it is very hard to review.
>
> Ideally, we try to do small patches one after one, each patch doing a
> small, focused (but still self consistent) change at a time.
>
> Would it be possible to first do the context-menu disabling thing in a
> separate first patch alone?
>
> I think we are often more lenient about patches on the TortoiseHg
> project compared to the Mercurial project itself, but observing
> http://mercurial.selenic.com/wiki/ContributingChanges#Organizing_patches
> can still be helpful.
>

I see.
I will sendseparate patches.

>> - static_cast<DWORD>(myFiles[i].size()),&dwWritten, 0
>> + tempfileHandle, str_file.c_str(),
>> + static_cast<DWORD>(str_file.size()),&dwWritten, 0
>> );
>> - WriteFile(tempfileHandle, "\n", 1,&dwWritten, 0);
>> + WriteFile(tempfileHandle, "\n", sizeof(char),&dwWritten, 0);


>> }
>> CloseHandle(tempfileHandle);
>> - hgcmd += " --listfile " + Quote(tempfile);
>> + hgcmd += listfile_opt + Quote(tempfile);
>> }
>>
>> - LaunchCommand(hgcmd, cwd);
>> + std::wstring run_dir ;
>> + std::wstring root = GetHgRepoRoot(cwd);
>> + if ( ! root.empty() )
>> + {
>> + run_dir = root ;
>> + }
>> + else
>> + {
>> + run_dir = cwd ;
>> + }
>> + LaunchCommand(hgcmd, run_dir);
>> InitStatus::check();
>> }
>>
>
> I do not understand this "if ( ! root.empty() )" part. Why are you doing
> this?
>
> If it is needed, could you do this in a separate patch (before doing the
> big unicode change)?
>

It fixed launching "thgw add/log/etc." problem in sub directory which contains 0x5c.
In Japanese:
https://bitbucket.org/marutosi/tortoisehg/wiki/Before-enable-win32mbcs
I will senda separate patch later.

Reply all
Reply to author
Forward
0 new messages