OSDN Git Service

Merge with stable
[winmerge-jp/winmerge-jp.git] / ShellExtension / WinMergeShell.cpp
index a15f93c..7648b98 100644 (file)
@@ -44,7 +44,6 @@
 #include "WinMergeShell.h"
 #include "UnicodeString.h"
 #include "RegKey.h"
-#include "coretools.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -55,7 +54,6 @@ enum ExtensionFlags
 {
        EXT_ENABLED = 0x01, /**< ShellExtension enabled/disabled. */
        EXT_ADVANCED = 0x02, /**< Advanced menuitems enabled/disabled. */
-       EXT_SUBFOLDERS = 0x04, /**< Subfolders included by default? */
 };
 
 /// Max. filecount to select
@@ -64,6 +62,7 @@ static const int MaxFileCount = 3;
 #define REGDIR _T("Software\\Thingamahoochie\\WinMerge")
 static const TCHAR f_RegDir[] = REGDIR;
 static const TCHAR f_RegLocaleDir[] = REGDIR _T("\\Locale");
+static const TCHAR f_RegSettingsDir[] = REGDIR _T("\\Settings");
 
 /**
  * @name Registry valuenames.
@@ -79,6 +78,8 @@ static const TCHAR f_RegValuePath[] = _T("Executable");
 static const TCHAR f_RegValuePriPath[] = _T("PriExecutable");
 /** LanguageId */
 static const TCHAR f_LanguageId[] = _T("LanguageId");
+/** Recurse */
+static const TCHAR f_Recurse[] = _T("Recurse");
 /*@}*/
 
 /**
@@ -112,13 +113,17 @@ public:
 
                m_lcidOld = GetThreadLocale();
 
-               int iLangId = reg.ReadDword(f_LanguageId, (DWORD) - 1);
+               int iLangId = reg.ReadDword(f_LanguageId, (DWORD)-1);
                if (iLangId != -1)
+               {
                        SetThreadLocale(MAKELCID(iLangId, SORT_DEFAULT));
+                       SetThreadUILanguage(iLangId);
+               }
        }
        ~CWinMergeTempLocale()
        {
                SetThreadLocale(m_lcidOld);
+               SetThreadUILanguage(LANGIDFROMLCID(m_lcidOld));
        }
 };
 
@@ -136,6 +141,47 @@ static String GetResourceString(UINT resourceID)
        return strResource;
 }
 
+static HBITMAP MakeBitmapBackColorTransparent(HBITMAP hbmSrc)
+{
+       HDC hdcSrc = CreateCompatibleDC(NULL);
+       BITMAP bm;
+       GetObject(hbmSrc, sizeof(bm), &bm);
+       HBITMAP hbmSrcOld = (HBITMAP)SelectObject(hdcSrc, hbmSrc);
+       BITMAPINFO bi = {0};
+       bi.bmiHeader.biSize = sizeof BITMAPINFOHEADER;
+       bi.bmiHeader.biPlanes = 1;
+       bi.bmiHeader.biBitCount = 32;
+       bi.bmiHeader.biCompression = BI_RGB;
+       bi.bmiHeader.biWidth = bm.bmWidth;
+       bi.bmiHeader.biHeight = -bm.bmHeight;
+       DWORD *pBits = NULL;
+       HBITMAP hbmNew = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
+       if (pBits)
+       {
+               COLORREF clrTP = GetPixel(hdcSrc, 0, 0);
+               int bR = GetRValue(clrTP), bG = GetGValue(clrTP), bB = GetBValue(clrTP);
+       
+               for (int y = 0; y < bm.bmHeight; ++y)
+               {
+                       for (int x = 0; x < bm.bmWidth; ++x)
+                       {
+                               COLORREF clrCur = GetPixel(hdcSrc, x, y);
+                               int cR = GetRValue(clrCur), cG = GetGValue(clrCur), cB = GetBValue(clrCur);
+                               if (!(abs(cR - bR) <= 1 && abs(cG - bG) <= 1 && abs(cB - bB) <= 1))
+                               {
+                                       pBits[y * bm.bmWidth + x] = cB | (cG << 8) | (cR << 16) | 0xFF000000;
+                               }
+                       }
+               }
+       }
+
+       SelectObject(hdcSrc, hbmSrcOld);
+       DeleteDC(hdcSrc);
+
+       return hbmNew;
+}
+
+
 /////////////////////////////////////////////////////////////////////////////
 // CWinMergeShell
 
@@ -143,15 +189,39 @@ static String GetResourceString(UINT resourceID)
 CWinMergeShell::CWinMergeShell()
 {
        m_dwMenuState = 0;
+       int cx = GetSystemMetrics(SM_CXMENUCHECK);
+       int cy = GetSystemMetrics(SM_CYMENUCHECK);
+       int id_fileicon = cx > 16 ? IDB_WINMERGE32 : IDB_WINMERGE;
+       int id_diricon = cx > 16 ? IDB_WINMERGEDIR32 : IDB_WINMERGEDIR;
 
        // compress or stretch icon bitmap according to menu item height
-       m_MergeBmp = (HBITMAP)LoadImage(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_WINMERGE), IMAGE_BITMAP,
-                       GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), LR_DEFAULTCOLOR);
+       HBITMAP hMergeBmp = (HBITMAP)LoadImage(_Module.GetModuleInstance(), MAKEINTRESOURCE(id_fileicon), IMAGE_BITMAP,
+                       cx, cy, LR_DEFAULTCOLOR);
+       HBITMAP hMergeDirBmp = (HBITMAP)LoadImage(_Module.GetModuleInstance(), MAKEINTRESOURCE(id_diricon), IMAGE_BITMAP,
+                       cx, cy, LR_DEFAULTCOLOR);
+
+       OSVERSIONINFO osvi;
+       osvi.dwOSVersionInfoSize = sizeof OSVERSIONINFO;
+       GetVersionEx(&osvi);
+       if (osvi.dwMajorVersion >= 6)
+       {
+               m_MergeBmp = MakeBitmapBackColorTransparent(hMergeBmp);
+               DeleteObject(hMergeBmp);
+
+               m_MergeDirBmp = MakeBitmapBackColorTransparent(hMergeDirBmp);
+               DeleteObject(hMergeDirBmp);
+       }
+       else
+       {
+               m_MergeBmp = hMergeBmp;
+               m_MergeDirBmp = hMergeDirBmp;
+       }
 }
 
 /// Default destructor, unloads bitmap
 CWinMergeShell::~CWinMergeShell()
 {
+       DeleteObject(m_MergeDirBmp);
        DeleteObject(m_MergeBmp);
 }
 
@@ -219,20 +289,26 @@ HRESULT CWinMergeShell::Initialize(LPCITEMIDLIST pidlFolder,
                GlobalUnlock(stg.hGlobal);
                ReleaseStgMedium(&stg);
        }
+       else
+       {
+               m_nSelectedItems = 0;
+       }
 
-       // No item selected - selection is the folder background
+               // No item selected - selection is the folder background
        if (pidlFolder)
        {
                TCHAR szPath[MAX_PATH] = {0};
 
                if (SHGetPathFromIDList(pidlFolder, szPath))
                {
-                       m_strPaths[0] = szPath;
-                       m_nSelectedItems = 1;
+                       if (m_nSelectedItems < MaxFileCount)
+                               m_strPaths[m_nSelectedItems++] = szPath;
                        hr = S_OK;
                }
                else
+               {
                        hr = E_INVALIDARG;
+               }
        }
        return hr;
 }
@@ -340,8 +416,8 @@ HRESULT CWinMergeShell::InvokeCommand(LPCMINVOKECOMMANDINFO pCmdInfo)
        if (!GetWinMergeDir(strWinMergePath))
                return S_FALSE;
 
-       // Check that file we are trying to execute exists and is executable
-       if (!CheckExecutable(strWinMergePath))
+       // Check that file we are trying to execute exists
+       if (!PathFileExists(strWinMergePath.c_str()))
                return S_FALSE;
 
        if (LOWORD(pCmdInfo->lpVerb) == 0)
@@ -445,26 +521,6 @@ BOOL CWinMergeShell::GetWinMergeDir(String &strDir)
        return TRUE;
 }
 
-/// Checks if given file exists and is executable
-BOOL CWinMergeShell::CheckExecutable(String path)
-{
-       String sExt;
-       SplitFilename(path.c_str(), NULL, NULL, &sExt);
-
-       // Check extension
-       if (_tcsicmp(sExt.c_str(), _T("exe")) == 0 ||
-                       _tcsicmp(sExt.c_str(), _T("cmd")) == 0 ||
-                       _tcsicmp(sExt.c_str(), _T("bat")) == 0)
-       {
-               // Check if file exists
-               struct _stati64 statBuffer;
-               int nRetVal = _tstati64(path.c_str(), &statBuffer);
-               if (nRetVal > -1)
-                       return TRUE;
-       }
-       return FALSE;
-}
-
 /// Create menu for simple mode
 int CWinMergeShell::DrawSimpleMenu(HMENU hmenu, UINT uMenuIndex,
                UINT uidFirstCmd)
@@ -473,8 +529,9 @@ int CWinMergeShell::DrawSimpleMenu(HMENU hmenu, UINT uMenuIndex,
        InsertMenu(hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd, strMenu.c_str());
 
        // Add bitmap
-       if (m_MergeBmp != NULL)
-               SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, m_MergeBmp, NULL);
+       HBITMAP hBitmap = PathIsDirectory(m_strPaths[0].c_str()) ? m_MergeDirBmp : m_MergeBmp;
+       if (hBitmap != NULL)
+               SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, hBitmap, NULL);
 
        // Show menu item as grayed if more than two items selected
        if (m_nSelectedItems > MaxFileCount)
@@ -536,11 +593,12 @@ int CWinMergeShell::DrawAdvancedMenu(HMENU hmenu, UINT uMenuIndex,
        }
 
        // Add bitmap
-       if (m_MergeBmp != NULL)
+       HBITMAP hBitmap = PathIsDirectory(m_strPaths[0].c_str()) ? m_MergeDirBmp : m_MergeBmp;
+       if (hBitmap != NULL)
        {
                if (nItemsAdded == 2)
-                       SetMenuItemBitmaps(hmenu, uMenuIndex - 1, MF_BYPOSITION, m_MergeBmp, NULL);
-               SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, m_MergeBmp, NULL);
+                       SetMenuItemBitmaps(hmenu, uMenuIndex - 1, MF_BYPOSITION, hBitmap, NULL);
+               SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, hBitmap, NULL);
        }
 
        // Show menu item as grayed if more than two items selected
@@ -608,12 +666,13 @@ String CWinMergeShell::GetHelpText(UINT_PTR idCmd)
 String CWinMergeShell::FormatCmdLine(const String &winmergePath,
                const String &path1, const String &path2, BOOL bAlterSubFolders)
 {
-       String strCommandline(winmergePath);
+       String strCommandline = _T("\"") + winmergePath + _T("\"");
 
        // Check if user wants to use context menu
        BOOL bSubfoldersByDefault = FALSE;
-       if (m_dwContextMenuEnabled & EXT_SUBFOLDERS) // User wants subfolders by def
-               bSubfoldersByDefault = TRUE;
+       CRegKeyEx reg;
+       if (reg.Open(HKEY_CURRENT_USER, f_RegSettingsDir) == ERROR_SUCCESS)
+               bSubfoldersByDefault = reg.ReadBool(f_Recurse, FALSE);
 
        if (bAlterSubFolders && !bSubfoldersByDefault)
                strCommandline += _T(" /r");