OSDN Git Service

Merge with stable
authorsdottaka <sdottaka@users.sourceforge.net>
Fri, 20 Feb 2015 10:32:10 +0000 (19:32 +0900)
committersdottaka <sdottaka@users.sourceforge.net>
Fri, 20 Feb 2015 10:32:10 +0000 (19:32 +0900)
132 files changed:
1  2 
Src/7zCommon.cpp
Src/AboutDlg.cpp
Src/AboutDlg.h
Src/CCPromptDlg.cpp
Src/CCPromptDlg.h
Src/ChildFrm.cpp
Src/Common/ClipBoard.h
Src/Common/LanguageSelect.cpp
Src/Common/LanguageSelect.h
Src/Common/MDITabBar.cpp
Src/Common/PreferencesDlg.cpp
Src/Common/PreferencesDlg.h
Src/Common/RegKey.cpp
Src/Common/ShellFileOperations.h
Src/Common/UnicodeString.cpp
Src/Common/UnicodeString.h
Src/Common/unicoder.cpp
Src/ConfirmFolderCopyDlg.cpp
Src/ConfirmFolderCopyDlg.h
Src/Constants.h
Src/DiffItem.h
Src/DiffList.cpp
Src/DiffViewBar.cpp
Src/DirActions.cpp
Src/DirCmpReport.cpp
Src/DirCmpReportDlg.cpp
Src/DirCmpReportDlg.h
Src/DirColsDlg.cpp
Src/DirColsDlg.h
Src/DirDoc.cpp
Src/DirDoc.h
Src/DirFrame.cpp
Src/DirItem.cpp
Src/DirTravel.cpp
Src/DirView.cpp
Src/DirView.h
Src/DirViewColItems.cpp
Src/DirViewColItems.h
Src/EditorFilepathBar.cpp
Src/EditorFilepathBar.h
Src/Environment.cpp
Src/FileActionScript.cpp
Src/FileActionScript.h
Src/FileFilterHelper.cpp
Src/FileFiltersDlg.cpp
Src/FileFiltersDlg.h
Src/FileOrFolderSelect.cpp
Src/FileOrFolderSelect.h
Src/FileTextEncoding.cpp
Src/FileTransform.h
Src/FilepathEdit.cpp
Src/FilepathEdit.h
Src/HexMergeDoc.cpp
Src/HexMergeFrm.cpp
Src/HexMergeView.cpp
Src/IListCtrl.h
Src/IListCtrlImpl.h
Src/ImgMergeFrm.cpp
Src/LineFiltersDlg.cpp
Src/LineFiltersDlg.h
Src/LoadSaveCodepageDlg.cpp
Src/LoadSaveCodepageDlg.h
Src/LocationBar.cpp
Src/LocationView.cpp
Src/MainFrm.cpp
Src/MainFrm.h
Src/Merge.cpp
Src/Merge.h
Src/Merge.vcxproj
Src/Merge.vcxproj.filters
Src/MergeApp.h
Src/MergeCmdLineInfo.cpp
Src/MergeDoc.cpp
Src/MergeDocLineDiffs.cpp
Src/MergeEditView.cpp
Src/MergeEditView.h
Src/OpenView.cpp
Src/OptionsDef.h
Src/OptionsInit.cpp
Src/PatchDlg.cpp
Src/PatchDlg.h
Src/PatchTool.cpp
Src/PatchTool.h
Src/PathContext.cpp
Src/PluginManager.h
Src/Plugins.cpp
Src/PluginsListDlg.cpp
Src/PluginsListDlg.h
Src/ProjectFilePathsDlg.cpp
Src/ProjectFilePathsDlg.h
Src/PropArchive.cpp
Src/PropArchive.h
Src/PropBackups.cpp
Src/PropBackups.h
Src/PropCodepage.cpp
Src/PropCodepage.h
Src/PropCompare.cpp
Src/PropCompare.h
Src/PropCompareFolder.cpp
Src/PropCompareFolder.h
Src/PropEditor.cpp
Src/PropEditor.h
Src/PropGeneral.cpp
Src/PropGeneral.h
Src/PropRegistry.cpp
Src/PropRegistry.h
Src/PropShell.cpp
Src/PropShell.h
Src/PropTextColors.cpp
Src/PropTextColors.h
Src/PropVss.cpp
Src/PropVss.h
Src/SaveClosingDlg.cpp
Src/SaveClosingDlg.h
Src/SelectUnpackerDlg.cpp
Src/SelectUnpackerDlg.h
Src/SharedFilterDlg.cpp
Src/SourceControl.cpp
Src/StdAfx.cpp
Src/StdAfx.h
Src/TempFile.cpp
Src/TestFilterDlg.cpp
Src/TestFilterDlg.h
Src/VSSHelper.cpp
Src/VssPromptDlg.cpp
Src/VssPromptDlg.h
Src/WMGotoDlg.cpp
Src/WMGotoDlg.h
Src/WaitStatusCursor.cpp
Src/WaitStatusCursor.h
Src/paths.cpp
Src/paths.h

 -/////////////////////////////////////////////////////////////////////////////
 -//    WinMerge:  an interactive diff/merge utility
 -//    Copyright (C) 1997-2000  Thingamahoochie Software
 -//    Author: Dean Grimm
 -//
 -//    This program is free software; you can redistribute it and/or modify
 -//    it under the terms of the GNU General Public License as published by
 -//    the Free Software Foundation; either version 2 of the License, or
 -//    (at your option) any later version.
 -//
 -//    This program is distributed in the hope that it will be useful,
 -//    but WITHOUT ANY WARRANTY; without even the implied warranty of
 -//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 -//    GNU General Public License for more details.
 -//
 -//    You should have received a copy of the GNU General Public License
 -//    along with this program; if not, write to the Free Software
 -//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 -//
 -/////////////////////////////////////////////////////////////////////////////
 -
 -/* 7zCommon.cpp: Implement 7z related classes and functions
 - * Copyright (c) 2003 Jochen Tucht
 - *
 - * Remarks:   Different versions of 7-Zip are interfaced through specific
 - *                    versions of Merge7z (Merge7z311.dll, Merge7z312.dll, etc.)
 - *                    WinMerge can either use an installed copy of the 7-Zip software,
 - *                    or fallback to a local set of 7-Zip DLLs, which are to be included
 - *                    in the WinMerge binary distribution.
 - *
 - *                    Fallback policies are as follows:
 - *
 - *                    1. Detect 7-Zip version installed (XXX).
 - *                    2. If there is a Merge7zXXX.dll, be happy to use it
 - *                    3. Detect 7-Zip version from WinMerge distribution (YYY).
 - *                    4. If there is a Merge7zYYY.dll, be happy to use it.
 - *                    5. Sorry, no way.
 - *
 - *                    These rules can be customized by setting a registry variable
 - *                    *Merge7z/Enable* of type DWORD to one of the following values:
 - *
 - *                    0 - Entirely disable 7-Zip integration.
 - *                    1 - Use installed 7-Zip if present. Otherwise, use local 7-Zip.
 - *                    2 - Always use local 7-Zip.
 - *
 -
 -Please mind 2. a) of the GNU General Public License, and log your changes below.
 -
 -DATE:         BY:                                     DESCRIPTION:
 -==========    ==================      ================================================
 -2003-12-09    Jochen Tucht            Created
 -2003-12-16    Jochen Tucht            Properly generate .tar.gz and .tar.bz2
 -2003-12-16    Jochen Tucht            Obtain long path to temporary folder
 -2004-01-20    Jochen Tucht            Complain only once if Merge7z*.dll is missing
 -2004-01-25    Jochen Tucht            Fix bad default for OPENFILENAME::nFilterIndex
 -2004-03-15    Jochen Tucht            Fix Visual Studio 2003 build issue
 -2004-04-13    Jochen Tucht            Avoid StrNCat to get away with shlwapi 4.70
 -2004-08-25    Jochen Tucht            More explicit error message
 -2004-10-17    Jochen Tucht            Leave decision whether to recurse into folders
 -                                                              to enumerator (Mask.Recurse)
 -2004-11-03    Jochen Tucht            FIX [1048997] as proposed by Kimmo 2004-11-02
 -2005-01-15    Jochen Tucht            Read 7-Zip version from 7zip_pad.xml
 -                                                              Set Merge7z UI language if DllBuild_Merge7z >= 9
 -2005-01-22    Jochen Tucht            Better explain what's present/missing/outdated
 -2005-02-05    Jochen Tucht            Fall back to IDD_MERGE7ZMISMATCH template from
 -                                                              .exe if .lang file isn't up to date.
 -2005-02-26    Jochen Tucht            Add download link to error message
 -2005-02-26    Jochen Tucht            Use WinAPI to obtain ISO language/region codes
 -2005-02-27    Jochen Tucht            FIX [1152375]
 -2005-04-24    Kimmo Varis                     Don't use DiffContext exported from DirView
 -2005-06-08    Kimmo Varis                     Use DIFFITEM, not reference to it (hopefully only
 -                                                              temporarily, to sort out new directory compare)
 -2005-06-22    Jochen Tucht            Change recommended version of 7-Zip to 4.20
 -                                                              Remove noise from Nagbox
 -2005-07-03    Jochen Tucht            DIFFITEM has changed due to RFE [ 1205516 ]
 -2005-07-04    Jochen Tucht            New global ArchiveGuessFormat() checks for
 -                                                              formats to be handled by external command line
 -                                                              tools. These take precedence over Merge7z
 -                                                              internal handlers.
 -2005-07-05    Jochen Tucht            Move to Merge7z::Format::GetDefaultName() to
 -                                                              build intermediate filenames for multi-step
 -                                                              compression.
 -2005-07-15    Jochen Tucht            Remove external command line tool integration
 -                                                              for now. Rethink about it after 2.4 branch.
 -2005-08-20    Jochen Tucht            Option to guess archive format by signature
 -                                                              Map extensions through ExternalArchiveFormat.ini
 -2005-08-23    Jochen Tucht            Option to entirely disable 7-Zip integration
 -2007-01-04    Kimmo Varis                     Convert using COptionsMgr for options.
 -2007-06-16    Jochen Neubeck          FIX [1723263] "Zip --> Both" operation...
 -2007-12-22    Jochen Neubeck          Fix Merge7z UI lang for new translation system
 -                                                              Change recommended version of 7-Zip to 4.57
 -2010-05-16    Jochen Neubeck          Read 7-Zip version from 7z.dll (which has long
 -                                                              ago replaced the various format and codec DLLs)
 -                                                              Change recommended version of 7-Zip to 4.65
 -*/
 -
 -
 -#include "stdafx.h"
 -#include "7zCommon.h"
 -#include <afxinet.h>
 -#include <shlwapi.h>
 -#include <paths.h>
 -#include "OptionsDef.h"
 -#include "OptionsMgr.h"
 -#include "Merge.h"            // DirDocFilter theApp GetOptionsMgr()
 -#include "resource.h"
 -#include "DirDoc.h"
 -//#include "ExternalArchiveFormat.h"
 -#include "version.h"
 -#include "Environment.h"
 -#include "Merge7zFormatRegister.h"
 -
 -#ifdef _DEBUG
 -#define new DEBUG_NEW
 -#undef THIS_FILE
 -static char THIS_FILE[] = __FILE__;
 -#endif
 -
 -/**
 - * @brief Proxy for Merge7z
 - */
 -static __declspec(thread) Merge7z::Proxy m_Merge7z =
 -{
 -      { 0, 0, DllBuild_Merge7z, },
 -      "Merge7z%u%02u"DECORATE_U".dll",
 -      "Merge7z",
 -      NULL
 -};
 -
 -std::vector<Merge7z::Format *(*)(const String& path)> Merge7zFormatRegister::optionalFormats;
 -
 -bool IsArchiveFile(const String& pszFile)
 -{
 -      try {
 -              Merge7z::Format *piHandler = ArchiveGuessFormat(pszFile);
 -              if (piHandler)
 -                      return TRUE;
 -              else
 -                      return FALSE;
 -      }
 -      catch (CException *e)
 -      {
 -              e->Delete();
 -              return FALSE;
 -      }
 -      return FALSE;
 -}
 -
 -/**
 - * @brief Wrap Merge7z::GuessFormat() to allow for some customizing:
 - * - Check if 7-Zip integration is enabled.
 - * - Check for filename extension mappings.
 - */
 -Merge7z::Format *ArchiveGuessFormat(const String& path)
 -{
 -      if (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE) == 0)
 -              return NULL;
 -      if (paths_IsDirectory(path))
 -              return NULL;
 -      String path2(path);
 -      // Map extensions through ExternalArchiveFormat.ini
 -      static TCHAR null[] = _T("");
 -      static const TCHAR section[] = _T("extensions");
 -      String entry = paths_FindExtension(path);
 -      TCHAR value[20];
 -      static LPCTSTR filename = NULL;
 -      if (filename == NULL)
 -      {
 -              TCHAR cPath[INTERNET_MAX_PATH_LENGTH];
 -              DWORD cchPath = SearchPath(NULL, _T("ExternalArchiveFormat.ini"), NULL,
 -                      INTERNET_MAX_PATH_LENGTH, cPath, NULL);
 -              filename = cchPath && cchPath < INTERNET_MAX_PATH_LENGTH ? StrDup(cPath) : null;
 -      }
 -      if (*filename &&
 -              GetPrivateProfileString(section, entry.c_str(), null, value, 20, filename) &&
 -              *value == '.')
 -      {
 -              // Remove end-of-line comments (in string returned from GetPrivateProfileString)
 -              // that is, remove semicolon & whatever follows it
 -              if (LPTSTR p = StrChr(value, ';'))
 -              {
 -                      *p = '\0';
 -                      StrTrim(value, _T(" \t"));
 -              }
 -              path2 = value;
 -      }
 -
 -      // PATCH [ 1229867 ] RFE [ 1205516 ], RFE [ 887948 ], and other issues
 -      // command line integration portion is not yet applied
 -      // so following code not yet valid, so temporarily commented out
 -      // Look for command line tool first
 -      /*Merge7z::Format *pFormat;
 -      if (CExternalArchiveFormat::GuessFormat(path, pFormat))
 -      {
 -              return pFormat;
 -      }*/
 -      // Default to Merge7z*.dll
 -
 -      try
 -      {
 -              Merge7z::Format *pFormat = m_Merge7z->GuessFormat(path2.c_str());
 -              if (!pFormat)
 -                      pFormat = Merge7zFormatRegister::GuessFormat(path2);
 -              return pFormat;
 -      }
 -      catch (...)
 -      {
 -              Merge7z::Format *pFormat = Merge7zFormatRegister::GuessFormat(path2);
 -              if (pFormat)
 -                      return pFormat;
 -              throw;
 -      }
 -}
 -
 -/**
 - * @brief Self-initializing raw C character buffer class.
 - */
 -template<class TYPE, size_t SIZE> struct CRawString
 -{
 -      enum { Size = SIZE };
 -      TYPE Data[SIZE];
 -      CRawString()
 -      {
 -              Data[0] = 0;
 -      }
 -};
 -
 -/**
 - * @brief Exception class for more explicit error message.
 - */
 -class C7ZipMismatchException : public CException
 -{
 -public:
 -      C7ZipMismatchException(DWORD dwVer7zInstalled, DWORD dwVer7zLocal, CException *pCause)
 -      {
 -              m_dwVer7zInstalled = dwVer7zInstalled;
 -              m_dwVer7zLocal = dwVer7zLocal;
 -              m_pCause = pCause;
 -      }
 -      ~C7ZipMismatchException()
 -      {
 -              if (m_pCause)
 -                      m_pCause->Delete();
 -      }
 -      virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);
 -protected:
 -      DWORD m_dwVer7zInstalled;
 -      DWORD m_dwVer7zLocal;
 -      CException *m_pCause;
 -      BOOL m_bShowAllways;
 -      static const DWORD m_dwVer7zRecommended;
 -      static const TCHAR m_strRegistryKey[];
 -      static const TCHAR m_strDownloadURL[];
 -      static INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
 -      static DWORD FormatVersion(LPTSTR, LPTSTR, DWORD);
 -};
 -
 -/**
 - * @brief Recommended version of 7-Zip.
 - */
 -const DWORD C7ZipMismatchException::m_dwVer7zRecommended = DWORD MAKELONG(65,4);
 -
 -/**
 - * @brief Registry key for C7ZipMismatchException's ReportError() popup.
 - */
 -const TCHAR C7ZipMismatchException::m_strRegistryKey[] = _T("7ZipMismatch");
 -
 -/**
 - * @brief Download URL for C7ZipMismatchException's ReportError() popup.
 - */
 -const TCHAR C7ZipMismatchException::m_strDownloadURL[] = _T("https://sourceforge.net/project/showfiles.php?group_id=13216&package_id=143957");
 -
 -/**
 - * @brief Retrieve build number of given DLL.
 - */
 -static DWORD NTAPI GetDllBuild(LPCTSTR cPath)
 -{
 -      HMODULE hModule = LoadLibrary(cPath);
 -      DLLVERSIONINFO dvi;
 -      dvi.cbSize = sizeof dvi;
 -      dvi.dwBuildNumber = ~0UL;
 -      if (hModule)
 -      {
 -              dvi.dwBuildNumber = 0UL;
 -              DLLGETVERSIONPROC DllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hModule, "DllGetVersion");
 -              if (DllGetVersion)
 -              {
 -                      DllGetVersion(&dvi);
 -              }
 -              FreeLibrary(hModule);
 -      }
 -      return dvi.dwBuildNumber;
 -}
 -
 -/**
 - * @brief Format Merge7z version number and plugin name, and retrieve DllBuild.
 - */
 -DWORD C7ZipMismatchException::FormatVersion(LPTSTR pcVersion, LPTSTR pcPluginName, DWORD dwVersion)
 -{
 -      *pcVersion = '\0';
 -      *pcPluginName = '\0';
 -      if (dwVersion)
 -      {
 -              wsprintf
 -              (
 -                      pcVersion, _T("%u.%02u"),
 -                      UINT HIWORD(dwVersion),
 -                      UINT LOWORD(dwVersion)
 -              );
 -              wsprintf
 -              (
 -                      pcPluginName,
 -                      sizeof(TCHAR) == 1 ? _T("Merge7z%u%02u.dll") : _T("Merge7z%u%02uU.dll"),
 -                      UINT HIWORD(dwVersion),
 -                      UINT LOWORD(dwVersion)
 -              );
 -      }
 -      return GetDllBuild(pcPluginName);
 -}
 -
 -/**
 - * @brief Populate ListBox with names/revisions of DLLs matching given pattern.
 - */
 -static void NTAPI DlgDirListDLLs(HWND hWnd, LPTSTR cPattern, int nIDListBox)
 -{
 -      HDC hDC = GetDC(hWnd);
 -      HFONT hFont = (HFONT)SendDlgItemMessage(hWnd, nIDListBox, WM_GETFONT, 0, 0);
 -      int cxView = (int)SendDlgItemMessage(hWnd, nIDListBox, LB_GETHORIZONTALEXTENT, 0, 0) - 8;
 -      HGDIOBJ hObject = SelectObject(hDC, hFont);
 -      WIN32_FIND_DATA ff;
 -      HANDLE h = FindFirstFile(cPattern, &ff);
 -      if (h != INVALID_HANDLE_VALUE)
 -      {
 -              do
 -              {
 -                      PathRemoveFileSpec(cPattern);
 -                      PathAppend(cPattern, ff.cFileName);
 -                      wsprintf(ff.cFileName, _T(" (dllbuild %04u)"), GetDllBuild(cPattern));
 -                      lstrcat(cPattern, ff.cFileName);
 -                      int cxText = (int)(WORD)GetTabbedTextExtent(hDC, cPattern, lstrlen(cPattern), 0, 0);
 -                      if (cxView < cxText)
 -                              cxView = cxText;
 -                      SendDlgItemMessage(hWnd, nIDListBox, LB_ADDSTRING, 0, (LPARAM)cPattern);
 -              } while (FindNextFile(h, &ff));
 -              FindClose(h);
 -      }
 -      SelectObject(hDC, hObject);
 -      ReleaseDC(hWnd, hDC);
 -      SendDlgItemMessage(hWnd, nIDListBox, LB_SETHORIZONTALEXTENT, cxView + 8, 0);
 -}
 -
 -/**
 - * @brief OwnerDraw states from recent SDK.
 - */
 -#define ODS_NOACCEL         0x0100
 -#define ODS_NOFOCUSRECT     0x0200
 -
 -/**
 - * @brief WM_DRAWITEM notification handlers.
 - */
 -struct CDrawItemStruct : DRAWITEMSTRUCT
 -{
 -      typedef CDrawItemStruct *From;
 -      void DrawWebLinkButton();
 -};
 -
 -void CDrawItemStruct::DrawWebLinkButton()
 -{
 -      CRawString<TCHAR,INTERNET_MAX_PATH_LENGTH> cText;
 -      int cchText = ::GetWindowText(hwndItem, cText.Data, cText.Size);
 -      COLORREF clrText = RGB(0,0,255);
 -      if (::GetWindowLong(hwndItem, GWL_STYLE) & BS_LEFTTEXT)
 -      {
 -              clrText = RGB(128,0,128);
 -      }
 -      RECT rcText = rcItem;
 -      ::DrawText(hDC, cText.Data, cchText, &rcText, DT_LEFT|DT_CALCRECT);
 -      ::OffsetRect(&rcText, 1, 0);
 -      rcItem.right = rcText.right + 1;
 -      rcItem.bottom = rcText.bottom + 1;
 -      switch (itemAction)
 -      {
 -      case ODA_DRAWENTIRE:
 -              ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcItem, 0, 0, 0);
 -              ::SetBkMode(hDC, TRANSPARENT);
 -              ::SetTextColor(hDC, clrText);
 -              ::DrawText(hDC, cText.Data, cchText, &rcText, DT_LEFT);
 -              rcText.top = rcText.bottom - 1;
 -              ::SetBkColor(hDC, clrText);
 -              ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcText, 0, 0, 0);
 -              if (itemState & ODS_FOCUS)
 -              {
 -              case ODA_FOCUS:
 -                      if (!(itemState & ODS_NOFOCUSRECT))
 -                      {
 -                              ::SetTextColor(hDC, 0);
 -                              ::SetBkColor(hDC, RGB(255,255,255));
 -                              ::SetBkMode(hDC, OPAQUE);
 -                              DrawFocusRect(hDC, &rcItem);
 -                      }
 -              }
 -              break;
 -      }
 -}
 -
 -/**
 - * @brief Load a cursor from COMCTL32.DLL.
 - */
 -HCURSOR NTAPI CommCtrl_LoadCursor(LPCTSTR lpCursorName)
 -{
 -      HMODULE hModule = GetModuleHandle(_T("COMCTL32.DLL"));
 -      return hModule ? LoadCursor(hModule, lpCursorName) : NULL;
 -}
 -
 -/**
 - * @brief DLGPROC for C7ZipMismatchException's ReportError() popup.
 - */
 -INT_PTR CALLBACK C7ZipMismatchException::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 -{
 -      switch (uMsg)
 -      {
 -              case WM_INITDIALOG:
 -              {
 -                      theApp.TranslateDialog(hWnd);
 -                      if (GetDlgItem(hWnd, 9001) == NULL)
 -                      {
 -                              // Dialog template isn't up to date. Give it a second chance.
 -                              EndDialog(hWnd, -1);
 -                              return FALSE;
 -                      }
 -                      C7ZipMismatchException *pThis = (C7ZipMismatchException *)lParam;
 -                      CRawString<TCHAR,2600> cText;
 -                      CRawString<TCHAR,80> cPresent, cMissing, cOutdated, cNone, cPlugin;
 -                      if (pThis->m_pCause)
 -                      {
 -                              pThis->m_pCause->GetErrorMessage(cText.Data, cText.Size);
 -                              SetDlgItemText(hWnd, 107, cText.Data);
 -                      }
 -                      else
 -                      {
 -                              GetDlgItemText(hWnd, 107, cText.Data, cText.Size);
 -                              switch (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE))
 -                              {
 -                              case 0:
 -                                      lstrcat(cText.Data, theApp.LoadString(IDS_MERGE7Z_ENABLE_0).c_str());
 -                                      break;
 -                              case 2:
 -                                      lstrcat(cText.Data, theApp.LoadString(IDS_MERGE7Z_ENABLE_2).c_str());
 -                                      break;
 -                              }
 -                              SetDlgItemText(hWnd, 107, cText.Data);
 -                      }
 -                      GetDlgItemText(hWnd, 112, cPresent.Data, cPresent.Size);
 -                      GetDlgItemText(hWnd, 122, cMissing.Data, cMissing.Size);
 -                      GetDlgItemText(hWnd, 132, cOutdated.Data, cOutdated.Size);
 -                      GetDlgItemText(hWnd, 120, cNone.Data, cNone.Size);
 -                      GetDlgItemText(hWnd, 102, cPlugin.Data, cPlugin.Size);
 -                      wsprintf(cText.Data, cPlugin.Data, DllBuild_Merge7z);
 -                      SetDlgItemText(hWnd, 102, cText.Data);
 -                      SetDlgItemText
 -                      (
 -                              hWnd, 109,
 -                              (
 -                                      pThis->m_dwVer7zRecommended == pThis->m_dwVer7zInstalled
 -                              ||      pThis->m_dwVer7zRecommended == pThis->m_dwVer7zLocal
 -                              ) ? cPresent.Data : cMissing.Data
 -                      );
 -                      DWORD dwDllBuild = FormatVersion(cText.Data, cPlugin.Data, pThis->m_dwVer7zRecommended);
 -                      SetDlgItemText(hWnd, 110, *cText.Data ? cText.Data : cNone.Data);
 -                      SetDlgItemText(hWnd, 111, cPlugin.Data);
 -                      SetDlgItemText(hWnd, 112, *cPlugin.Data == '\0' ? cPlugin.Data :
 -                              dwDllBuild == ~0 ? cMissing.Data : dwDllBuild < DllBuild_Merge7z ? cOutdated.Data : cPresent.Data);
 -                      dwDllBuild = FormatVersion(cText.Data, cPlugin.Data, pThis->m_dwVer7zInstalled);
 -                      SetDlgItemText(hWnd, 120, *cText.Data ? cText.Data : cNone.Data);
 -                      SetDlgItemText(hWnd, 121, cPlugin.Data);
 -                      SetDlgItemText(hWnd, 122, *cPlugin.Data == '\0' ? cPlugin.Data :
 -                              dwDllBuild == ~0 ? cMissing.Data : dwDllBuild < DllBuild_Merge7z ? cOutdated.Data : cPresent.Data);
 -                      dwDllBuild = FormatVersion(cText.Data, cPlugin.Data, pThis->m_dwVer7zLocal);
 -                      SetDlgItemText(hWnd, 130, *cText.Data ? cText.Data : cNone.Data);
 -                      SetDlgItemText(hWnd, 131, cPlugin.Data);
 -                      SetDlgItemText(hWnd, 132, *cPlugin.Data == '\0' ? cPlugin.Data :
 -                              dwDllBuild == ~0 ? cMissing.Data : dwDllBuild < DllBuild_Merge7z ? cOutdated.Data : cPresent.Data);
 -                      GetModuleFileName(0, cText.Data, MAX_PATH);
 -                      PathRemoveFileSpec(cText.Data);
 -                      PathAppend(cText.Data, _T("Merge7z*.dll"));
 -                      DlgDirListDLLs(hWnd, cText.Data, 105);
 -                      if (DWORD cchPath = GetEnvironmentVariable(_T("path"), 0, 0))
 -                      {
 -                              static const TCHAR cSep[] = _T(";");
 -                              LPTSTR pchPath = new TCHAR[cchPath];
 -                              GetEnvironmentVariable(_T("PATH"), pchPath, cchPath);
 -                              LPTSTR pchItem = pchPath;
 -                              while (int cchItem = StrCSpn(pchItem += StrSpn(pchItem, cSep), cSep))
 -                              {
 -                                      if (cchItem < MAX_PATH)
 -                                      {
 -                                              CopyMemory(cText.Data, pchItem, cchItem*sizeof*pchItem);
 -                                              cText.Data[cchItem] = 0;
 -                                              PathAppend(cText.Data, _T("Merge7z*.dll"));
 -                                              DlgDirListDLLs(hWnd, cText.Data, 105);
 -                                      }
 -                                      pchItem += cchItem;
 -                              }
 -                              delete[] pchPath;
 -                      }
 -                      if (SendDlgItemMessage(hWnd, 105, LB_GETCOUNT, 0, 0) == 0)
 -                      {
 -                              SendDlgItemMessage(hWnd, 105, LB_ADDSTRING, 0, (LPARAM) cNone.Data);
 -                      }
 -                      HICON hIcon = LoadIcon(0, IDI_EXCLAMATION);
 -                      SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
 -                      SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
 -                      if (pThis->m_bShowAllways)
 -                      {
 -                              ShowWindow(GetDlgItem(hWnd, 106), SW_HIDE);
 -                      }
 -              } return TRUE;
 -              case WM_DRAWITEM:
 -              {
 -                      switch (wParam)
 -                      {
 -                      case 108:
 -                              CDrawItemStruct::From(lParam)->DrawWebLinkButton();
 -                              break;
 -                      }
 -              } return TRUE;
 -              case WM_SETCURSOR:
 -              {
 -                      HCURSOR hCursor = 0;
 -                      switch (GetDlgCtrlID((HWND)wParam))
 -                      {
 -                      case 108:
 -                              hCursor = CommCtrl_LoadCursor(MAKEINTRESOURCE(108));
 -                              break;
 -                      }
 -                      if (hCursor)
 -                      {
 -                              SetCursor(hCursor);
 -                              SetWindowLongPtr(hWnd, DWLP_MSGRESULT, 1);
 -                              return TRUE;
 -                      }
 -              } return FALSE;
 -              case WM_COMMAND:
 -              {
 -                      switch (wParam)
 -                      {
 -                              case IDOK:
 -                              case IDCANCEL:
 -                              {
 -                                      LRESULT nDontShowAgain = SendDlgItemMessage(hWnd, 106, BM_GETCHECK, 0, 0);
 -                                      EndDialog(hWnd, MAKEWORD(IDOK, nDontShowAgain));
 -                              } break;
 -                              case 108:
 -                              {
 -                                      HINSTANCE h = ShellExecute(hWnd, _T("open"), m_strDownloadURL, 0, 0, SW_SHOWNORMAL);
 -                                      if ((UINT)h > 32)
 -                                      {
 -                                              LONG lStyle = ::GetWindowLong((HWND)lParam, GWL_STYLE);
 -                                              ::SetWindowLong((HWND)lParam, GWL_STYLE, lStyle|BS_LEFTTEXT);
 -                                              ::InvalidateRect((HWND)lParam, 0, TRUE);
 -                                      }
 -                                      else
 -                                      {
 -                                              MessageBeep(0);
 -                                      }
 -                              } break;
 -                      }
 -              } return TRUE;
 -      }
 -      return FALSE;
 -}
 -
 -/**
 - * @brief Tell user what went wrong and how she can help.
 - */
 -int C7ZipMismatchException::ReportError(UINT nType, UINT nMessageID)
 -{
 -      UINT_PTR response = -1;
 -      m_bShowAllways = nMessageID;
 -      if (!m_bShowAllways)
 -      {
 -              // Suppress error message in case 7-Zip is not installed.
 -              response =
 -              (
 -                      m_dwVer7zInstalled || m_dwVer7zLocal
 -              ?       (INT_PTR)(int)theApp.GetProfileInt(REGISTRY_SECTION_MESSAGEBOX, m_strRegistryKey, -1)
 -              :       IDOK
 -              );
 -      }
 -      if (response == -1)
 -      {
 -              HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();
 -              response = DialogBoxParam(AfxGetResourceHandle(), MAKEINTRESOURCE(IDD_MERGE7ZMISMATCH), hwndOwner, DlgProc, (LPARAM)this);
 -              if (response == -1)
 -              {
 -                      response = DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_MERGE7ZMISMATCH), hwndOwner, DlgProc, (LPARAM)this);
 -                      ASSERT(response != -1);
 -              }
 -              if (HIBYTE(response) == 1)
 -              {
 -                      theApp.WriteProfileInt(REGISTRY_SECTION_MESSAGEBOX, m_strRegistryKey, response = int LOBYTE(response));
 -              }
 -      }
 -      return response;
 -}
 -
 -/**
 - * @brief Check whether archive support is available.
 - */
 -int NTAPI HasZipSupport()
 -{
 -      static int HasZipSupport = -1;
 -      if (HasZipSupport == -1)
 -      {
 -              try
 -              {
 -                      m_Merge7z.operator->();
 -                      HasZipSupport = 1;
 -              }
 -              catch (CException *e)
 -              {
 -                      e->Delete();
 -                      HasZipSupport = 0;
 -              }
 -      }
 -      return HasZipSupport;
 -}
 -
 -/**
 - * @brief Tell user why archive support is not available.
 - */
 -void NTAPI Recall7ZipMismatchError()
 -{
 -      try
 -      {
 -              m_Merge7z.operator->();
 -      }
 -      catch (CException *e)
 -      {
 -              e->ReportError(MB_ICONEXCLAMATION, TRUE);
 -              e->Delete();
 -      }
 -}
 -
 -/**
 - * @brief Delete head of temp path context list, and return its parent context.
 - */
 -CTempPathContext *CTempPathContext::DeleteHead()
 -{
 -      CTempPathContext *pParent = m_pParent;
 -      delete this;
 -      return pParent;
 -}
 -
 -BOOL NTAPI IsMerge7zEnabled()
 -{
 -      return AfxGetApp()->GetProfileInt(_T("Merge7z"), _T("Enable"), 0);
 -}
 -
 -/**
 - * @brief Return installed or local version of 7-Zip.
 - */
 -DWORD NTAPI VersionOf7z(BOOL bLocal)
 -{
 -      TCHAR path[MAX_PATH];
 -      if (bLocal)
 -      {
 -              GetModuleFileName(0, path, sizeof path/sizeof*path);
 -              PathRemoveFileSpec(path);
 -      }
 -      else
 -      {
 -              static const TCHAR szSubKey[] = _T("Software\\7-Zip");
 -              static const TCHAR szValue[] = _T("Path");
 -              DWORD type = 0;
 -              DWORD size = sizeof path;
 -              SHGetValue(HKEY_LOCAL_MACHINE, szSubKey, szValue, &type, path, &size);
 -      }
 -      PathAppend(path, _T("7z.dll"));
 -      unsigned versionMS = 0;
 -      unsigned versionLS = 0;
 -      CVersionInfo(path).GetFixedFileVersion(versionMS, versionLS);
 -      return versionMS;
 -}
 -
 -/**
 - * @brief Access dll functions through proxy.
 - */
 -interface Merge7z *Merge7z::Proxy::operator->()
 -{
 -      // As long as the Merge7z*.DLL has not yet been loaded, Merge7z
 -      // [0] points to the name of the DLL (with placeholders for 7-
 -      // Zip major and minor version numbers). Once the DLL has been
 -      // loaded successfully, Merge7z[0] is set to NULL, causing the
 -      // if to fail on subsequent calls.
 -
 -      if (const char *format = Merge7z[0])
 -      {
 -              // Merge7z has not yet been loaded
 -
 -              char name[MAX_PATH];
 -              DWORD flags = ~0;
 -              CException *pCause = NULL;
 -              switch (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE))
 -              {
 -              case 1: //Use installed 7-Zip if present. Otherwise, use local 7-Zip.
 -                      if (DWORD ver = VersionOf7z(FALSE))
 -                      {
 -                              flags = Initialize::Default;
 -                              try
 -                              {
 -                                      wsprintfA(name, format, UINT HIWORD(ver), UINT LOWORD(ver));
 -                                      Merge7z[0] = name;
 -                                      stub.Load();
 -                                      break;
 -                              }
 -                              catch (CException *e)
 -                              {
 -                                      Merge7z[0] = format;
 -                                      pCause = e;
 -                              }
 -                      }
 -              case 2: //Always use local 7-Zip.
 -                      if (DWORD ver = VersionOf7z(TRUE))
 -                      {
 -                              flags = Initialize::Default | Initialize::Local7z;
 -                              try
 -                              {
 -                                      wsprintfA(name, format, UINT HIWORD(ver), UINT LOWORD(ver));
 -                                      Merge7z[0] = name;
 -                                      stub.Load();
 -                                      break;
 -                              }
 -                              catch (CException *e)
 -                              {
 -                                      Merge7z[0] = format;
 -                                      if (pCause) pCause->Delete();
 -                                      pCause = e;
 -                              }
 -                      }
 -              default:
 -                      throw new C7ZipMismatchException
 -                      (
 -                              VersionOf7z(FALSE),
 -                              VersionOf7z(TRUE),
 -                              pCause
 -                      );
 -              }
 -              LANGID wLangID = (LANGID)GetThreadLocale();
 -              flags |= wLangID << 16;
 -              if (GetOptionsMgr()->GetBool(OPT_ARCHIVE_PROBETYPE))
 -              {
 -                      flags |= Initialize::GuessFormatBySignature | Initialize::GuessFormatByExtension;
 -              }
 -              if (Merge7z[1])
 -                      ((interface Merge7z *)Merge7z[1])->Initialize(flags);
 -      }
 -      return ((interface Merge7z *)Merge7z[1]);
 -}
 -
 -/**
 - * @brief Tell Merge7z we are going to enumerate just 1 item.
 - */
 -UINT SingleItemEnumerator::Open()
 -{
 -      return 1;
 -}
 -
 -/**
 - * @brief Pass information about the item to Merge7z.
 - */
 -Merge7z::Envelope *SingleItemEnumerator::Enum(Item &item)
 -{
 -      item.Mask.Item = item.Mask.Name|item.Mask.FullPath|item.Mask.Recurse;
 -      item.Name = Name;
 -      item.FullPath = FullPath;
 -      return 0;
 -}
 -
 -/**
 - * @brief SingleFileEnumerator constructor.
 - */
 -SingleItemEnumerator::SingleItemEnumerator(LPCTSTR path, LPCTSTR FullPath, LPCTSTR Name)
 -: FullPath(FullPath)
 -, Name(Name)
 -{
 -}
 -
 -/**
 - * @brief Construct a CDirView::DirItemEnumerator.
 - *
 - * Argument *nFlags* controls operation as follows:
 - * LVNI_ALL:          Enumerate all items.
 - * LVNI_SELECTED:     Enumerate selected items only.
 - * Original:          Set folder prefix for first iteration to "original"
 - * Altered:                   Set folder prefix for second iteration to "altered"
 - * BalanceFolders:    Ensure that all nonempty folders on either side have a
 - *                                    corresponding folder on the other side, even if it is
 - *                                    empty (DirScan doesn't recurse into folders which
 - *                                    appear only on one side).
 - * DiffsOnly:         Enumerate diffs only.
 - */
 -CDirView::DirItemEnumerator::DirItemEnumerator(CDirView *pView, int nFlags)
 -: m_pView(pView)
 -, m_nFlags(nFlags)
 -{
 -      if (m_nFlags & Original)
 -      {
 -              m_rgFolderPrefix.push_back(_T("original"));
 -      }
 -      if (m_nFlags & Altered)
 -      {
 -              m_rgFolderPrefix.push_back(_T("altered"));
 -      }
 -      if (m_nFlags & BalanceFolders)
 -      {
 -              // Collect implied folders
 -              for (UINT i = Open() ; i-- ; )
 -              {
 -                      const DIFFITEM &di = Next();
 -                      if ((m_nFlags & DiffsOnly) && !m_pView->IsItemNavigableDiff(di))
 -                      {
 -                              continue;
 -                      }
 -                      if (m_bRight) 
 -                      {
 -                              // Enumerating items on right side
 -                              if (!di.diffcode.isSideFirstOnly())
 -                              {
 -                                      // Item is present on right side, i.e. folder is implied
 -                                      m_rgImpliedFoldersRight[di.diffFileInfo[1].path.get()] = PVOID(1);
 -                              }
 -                      }
 -                      else
 -                      {
 -                              // Enumerating items on left side
 -                              if (!di.diffcode.isSideSecondOnly())
 -                              {
 -                                      // Item is present on left side, i.e. folder is implied
 -                                      m_rgImpliedFoldersLeft[di.diffFileInfo[0].path.get()] = PVOID(1);
 -                              }
 -                      }
 -              }
 -      }
 -}
 -
 -/**
 - * @brief Initialize enumerator, return number of items to be enumerated.
 - */
 -UINT CDirView::DirItemEnumerator::Open()
 -{
 -      m_nIndex = -1;
 -      m_curFolderPrefix = m_rgFolderPrefix.begin();
 -      m_bRight = (m_nFlags & Right) != 0;
 -      size_t nrgFolderPrefix = m_rgFolderPrefix.size();
 -      if (nrgFolderPrefix)
 -      {
 -              m_strFolderPrefix = *m_curFolderPrefix++;
 -      }
 -      else
 -      {
 -              nrgFolderPrefix = 1;
 -      }
 -      return
 -      (
 -              m_nFlags & LVNI_SELECTED
 -      ?       pView(m_pView)->GetSelectedCount()
 -      :       pView(m_pView)->GetItemCount()
 -      ) * nrgFolderPrefix;
 -}
 -
 -/**
 - * @brief Return next item.
 - */
 -const DIFFITEM &CDirView::DirItemEnumerator::Next()
 -{
 -      enum {nMask = LVNI_FOCUSED|LVNI_SELECTED|LVNI_CUT|LVNI_DROPHILITED};
 -      while ((m_nIndex = pView(m_pView)->GetNextItem(m_nIndex, m_nFlags & nMask)) == -1)
 -      {
 -              m_strFolderPrefix = *m_curFolderPrefix++;
 -              m_bRight = TRUE;
 -      }
 -      return m_pView->GetDiffItem(m_nIndex);
 -}
 -
 -/**
 - * @brief Pass information about an item to Merge7z.
 - *
 - * Information is passed through struct Merge7z::DirItemEnumerator::Item.
 - * The *mask* member denotes which of the other members contain valid data.
 - * If *mask* is zero upon return, which will be the case if Enum() decides to
 - * leave the struct untouched, Merge7z will ignore the item.
 - * If Enum() allocates temporary storage for string members, it must also
 - * allocate an Envelope, providing a Free() method to free the temporary
 - * storage, along with the Envelope itself. The Envelope pointer is passed to
 - * Merge7z as the return value of the function. It is not meant to be a success
 - * indicator, so if no temporary storage is required, it is perfectly alright
 - * to return NULL.
 - */
 -Merge7z::Envelope *CDirView::DirItemEnumerator::Enum(Item &item)
 -{
 -      CDirDoc * pDoc = m_pView->GetDocument();
 -      const DIFFITEM &di = Next();
 -
 -      if ((m_nFlags & DiffsOnly) && !m_pView->IsItemNavigableDiff(di))
 -      {
 -              return 0;
 -      }
 -
 -      bool isSideFirst = di.diffcode.isSideFirstOnly();
 -      bool isSideSecond = di.diffcode.isSideSecondOnly();
 -
 -      Envelope *envelope = new Envelope;
 -
 -      const String &sFilename = m_bRight ? di.diffFileInfo[1].filename : di.diffFileInfo[0].filename;
 -      const String &sSubdir = m_bRight ? di.diffFileInfo[1].path : di.diffFileInfo[0].path;
 -      envelope->Name = sFilename;
 -      if (sSubdir.length())
 -      {
 -              envelope->Name.insert(0, _T("\\"));
 -              envelope->Name.insert(0, sSubdir);
 -      }
 -      envelope->FullPath = sFilename;
 -      envelope->FullPath.insert(0, _T("\\"));
 -      envelope->FullPath.insert(0, m_bRight ?
 -      di.getFilepath(1, pDoc->GetBasePath(1)) :
 -      di.getFilepath(0, pDoc->GetBasePath(0)));
 -
 -      UINT32 Recurse = item.Mask.Recurse;
 -
 -      if (m_nFlags & BalanceFolders)
 -      {
 -              if (m_bRight)
 -              {
 -                      // Enumerating items on right side
 -                      if (isSideFirst)
 -                      {
 -                              // Item is missing on right side
 -                              PVOID &implied = m_rgImpliedFoldersRight[di.diffFileInfo[0].path.get()];
 -                              if (!implied)
 -                              {
 -                                      // Folder is not implied by some other file, and has
 -                                      // not been enumerated so far, so enumerate it now!
 -                                      envelope->Name = di.diffFileInfo[0].path;
 -                                      envelope->FullPath = di.getFilepath(0, pDoc->GetBasePath(0));
 -                                      implied = PVOID(2); // Don't enumerate same folder twice!
 -                                      isSideFirst = false;
 -                                      Recurse = 0;
 -                              }
 -                      }
 -              }
 -              else
 -              {
 -                      // Enumerating items on left side
 -                      if (isSideSecond)
 -                      {
 -                              // Item is missing on left side
 -                              PVOID &implied = m_rgImpliedFoldersLeft[di.diffFileInfo[1].path.get()];
 -                              if (!implied)
 -                              {
 -                                      // Folder is not implied by some other file, and has
 -                                      // not been enumerated so far, so enumerate it now!
 -                                      envelope->Name = di.diffFileInfo[1].path;
 -                                      envelope->FullPath = di.getFilepath(1, pDoc->GetBasePath(1));
 -                                      implied = PVOID(2); // Don't enumerate same folder twice!
 -                                      isSideSecond = false;
 -                                      Recurse = 0;
 -                              }
 -                      }
 -              }
 -      }
 -
 -      if (m_bRight ? isSideFirst : isSideSecond)
 -      {
 -              return envelope;
 -      }
 -
 -      if (m_strFolderPrefix.length())
 -      {
 -              if (envelope->Name.length())
 -                      envelope->Name.insert(0, _T("\\"));
 -              envelope->Name.insert(0, m_strFolderPrefix);
 -      }
 -
 -      item.Mask.Item = item.Mask.Name|item.Mask.FullPath|item.Mask.CheckIfPresent|Recurse;
 -      item.Name = envelope->Name.c_str();
 -      item.FullPath = envelope->FullPath.c_str();
 -      return envelope;
 -}
 -
 -/**
 - * @brief Apply appropriate handlers from left to right.
 - */
 -bool CDirView::DirItemEnumerator::MultiStepCompressArchive(LPCTSTR path)
 -{
 -      DeleteFile(path);
 -      Merge7z::Format *piHandler = ArchiveGuessFormat(path);
 -      if (piHandler)
 -      {
 -              HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();
 -              CString pathIntermediate;
 -              SysFreeString(Assign(pathIntermediate, piHandler->GetDefaultName(hwndOwner, path)));
 -              String pathPrepend = path;
 -              pathPrepend.resize(pathPrepend.rfind('\\') + 1);
 -              pathIntermediate.Insert(0, pathPrepend.c_str());
 -              bool bDone = MultiStepCompressArchive(pathIntermediate);
 -              if (bDone)
 -              {
 -                      piHandler->CompressArchive(hwndOwner, path,
 -                              &SingleItemEnumerator(path, pathIntermediate));
 -                      DeleteFile(pathIntermediate);
 -              }
 -              else
 -              {
 -                      piHandler->CompressArchive(hwndOwner, path, this);
 -              }
 -              return true;
 -      }
 -      return false;
 -}
 -
 -/**
 - * @brief Generate archive from DirView items.
 - */
 -void CDirView::DirItemEnumerator::CompressArchive(LPCTSTR path)
 -{
 -      String strPath;
 -      if (path == 0)
 -      {
 -              // No path given, so prompt for path!
 -              static const TCHAR _T_Merge7z[] = _T("Merge7z");
 -              static const TCHAR _T_FilterIndex[] = _T("FilterIndex");
 -              // 7z311 can only write 7z, zip, and tar(.gz|.bz2) archives, so don't
 -              // offer other formats here!
 -              static const TCHAR _T_Filter[]
 -              (
 -                      _T("7z|*.7z|")
 -                      //_T("z|*.z|")
 -                      _T("zip|*.zip|")
 -                      _T("jar (zip)|*.jar|")
 -                      _T("ear (zip)|*.ear|")
 -                      _T("war (zip)|*.war|")
 -                      _T("xpi (zip)|*.xpi|")
 -                      //_T("rar|*.rar|")
 -                      _T("tar|*.tar|")
 -                      _T("tar.z|*.tar.z|")
 -                      _T("tar.gz|*.tar.gz|")
 -                      _T("tar.bz2|*.tar.bz2|")
 -                      //_T("tz|*.tz|")
 -                      _T("tgz|*.tgz|")
 -                      _T("tbz2|*.tbz2|")
 -                      //_T("lzh|*.lzh|")
 -                      //_T("cab|*.cab|")
 -                      //_T("arj|*.arj|")
 -                      //_T("deb|*.deb|")
 -                      //_T("rpm|*.rpm|")
 -                      //_T("cpio|*.cpio|")
 -                      //_T("|")
 -              );
 -              String strFilter; // = CExternalArchiveFormat::GetOpenFileFilterString();
 -              strFilter.insert(0, _T_Filter);
 -              strFilter += _T("|");
 -              CFileDialog dlg
 -              (
 -                      FALSE,
 -                      0,
 -                      0,
 -                      OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN,
 -                      strFilter.c_str()
 -              );
 -              dlg.m_ofn.nFilterIndex = AfxGetApp()->GetProfileInt(_T_Merge7z, _T_FilterIndex, 1);
 -              // Use extension from current filter as default extension:
 -              if (int i = dlg.m_ofn.nFilterIndex)
 -              {
 -                      dlg.m_ofn.lpstrDefExt = dlg.m_ofn.lpstrFilter;
 -                      while (*dlg.m_ofn.lpstrDefExt && --i)
 -                      {
 -                              dlg.m_ofn.lpstrDefExt += lstrlen(dlg.m_ofn.lpstrDefExt) + 1;
 -                              dlg.m_ofn.lpstrDefExt += lstrlen(dlg.m_ofn.lpstrDefExt) + 1;
 -                      }
 -                      if (*dlg.m_ofn.lpstrDefExt)
 -                      {
 -                              dlg.m_ofn.lpstrDefExt += lstrlen(dlg.m_ofn.lpstrDefExt) + 3;
 -                      }
 -              }
 -              if (dlg.DoModal() == IDOK)
 -              {
 -                      strPath = dlg.GetPathName();
 -                      path = strPath.c_str();
 -                      AfxGetApp()->WriteProfileInt(_T_Merge7z, _T_FilterIndex, dlg.m_ofn.nFilterIndex);
 -              }
 -      }
 -      if (path && !MultiStepCompressArchive(path))
 -      {
 -              LangMessageBox(IDS_UNKNOWN_ARCHIVE_FORMAT, MB_ICONEXCLAMATION);
 -      }
 -}
 -
 -/**
 - * @brief Collect files for SHFileOperation
 - */
 -void CDirView::DirItemEnumerator::CollectFiles(String &strBuffer)
 -{
 -      CDirDoc *pDoc = m_pView->GetDocument();
 -      const String sLeftRootPath = pDoc->GetBasePath(0);
 -      const String sRightRootPath = pDoc->GetBasePath(1);
 -      UINT i;
 -      int cchBuffer = 0;
 -      for (i = Open() ; i-- ; )
 -      {
 -              const DIFFITEM &di = Next();
 -              if (m_bRight ? m_pView->IsItemOpenableOnRightWith(di) : m_pView->IsItemOpenableOnLeftWith(di))
 -              {
 -                      cchBuffer +=
 -                      (
 -                              m_bRight ? di.getFilepath(1, sLeftRootPath) : di.getFilepath(0, sRightRootPath)
 -                      ).length() + (m_bRight ? di.diffFileInfo[1].filename : di.diffFileInfo[0].filename).get().length() + 2;
 -              }
 -      }
 -      strBuffer.resize(cchBuffer + 1);
 -      LPTSTR pchBuffer = &strBuffer[0];
 -      for (i = Open() ; i-- ; )
 -      {
 -              const DIFFITEM &di = Next();
 -              if (m_bRight ? m_pView->IsItemOpenableOnRightWith(di) : m_pView->IsItemOpenableOnLeftWith(di))
 -              {
 -                      pchBuffer += wsprintf
 -                      (
 -                              pchBuffer,
 -                              _T("%s\\%s"),
 -                              m_bRight ? di.getFilepath(1, sLeftRootPath).c_str() : di.getFilepath(0, sRightRootPath).c_str(),
 -                              m_bRight ? di.diffFileInfo[1].filename.get().c_str() : di.diffFileInfo[0].filename.get().c_str()
 -                      ) + 1;
 -              }
 -      }
 -      ASSERT(pchBuffer - &strBuffer[0] == cchBuffer);
 -}
 -
 -DecompressResult DecompressArchive(HWND hWnd, const PathContext& files)
 -{
 -      DecompressResult res(files, NULL, IS_EXISTING_DIR);
 -      try
 -      {
 -              String path;
 -              USES_CONVERSION;
 -              // Handle archives using 7-zip
 -              Merge7z::Format *piHandler;
 -              if (piHandler = ArchiveGuessFormat(res.files[0].c_str()))
 -              {
 -                      res.pTempPathContext = new CTempPathContext;
 -                      path = env_GetTempChildPath();
 -                      for (int index = 0; index < res.files.GetSize(); index++)
 -                              res.pTempPathContext->m_strDisplayRoot[index] = res.files[index];
 -                      if (res.files.GetSize() == 2 && res.files[0] == res.files[1])
 -                              res.files[1].erase();
 -                      do
 -                      {
 -                              if (FAILED(piHandler->DeCompressArchive(hWnd, res.files[0].c_str(), path.c_str())))
 -                                      break;
 -                              if (res.files[0].find(path) == 0)
 -                              {
 -                                      VERIFY(::DeleteFile(res.files[0].c_str()) || (LogErrorString(string_format(_T("DeleteFile(%s) failed"), res.files[0].c_str())), false));
 -                              }
 -                              BSTR pTmp = piHandler->GetDefaultName(hWnd, res.files[0].c_str());
 -                              res.files[0] = OLE2T(pTmp);
 -                              SysFreeString(pTmp);
 -                              res.files[0].insert(0, _T("\\"));
 -                              res.files[0].insert(0, path);
 -                      } while (piHandler = ArchiveGuessFormat(res.files[0].c_str()));
 -                      res.files[0] = path;
 -              }
 -              if (!res.files[1].empty() && (piHandler = ArchiveGuessFormat(res.files[1].c_str())))
 -              {
 -                      if (!res.pTempPathContext)
 -                      {
 -                              res.pTempPathContext = new CTempPathContext;
 -                              for (int index = 0; index < res.files.GetSize(); index++)
 -                                      res.pTempPathContext->m_strDisplayRoot[index] = res.files[index];
 -                      }
 -                      path = env_GetTempChildPath();
 -                      do
 -                      {
 -                              if (FAILED(piHandler->DeCompressArchive(hWnd, res.files[1].c_str(), path.c_str())))
 -                                      break;;
 -                              if (res.files[1].find(path) == 0)
 -                              {
 -                                      VERIFY(::DeleteFile(res.files[1].c_str()) || (LogErrorString(string_format(_T("DeleteFile(%s) failed"), res.files[1].c_str())), false));
 -                              }
 -                              BSTR pTmp = piHandler->GetDefaultName(hWnd, res.files[1].c_str());
 -                              res.files[1] = OLE2T(pTmp);
 -                              SysFreeString(pTmp);
 -                              res.files[1].insert(0, _T("\\"));
 -                              res.files[1].insert(0, path);
 -                      } while (piHandler = ArchiveGuessFormat(res.files[1].c_str()));
 -                      res.files[1] = path;
 -              }
 -              if (res.files.GetSize() > 2 && (piHandler = ArchiveGuessFormat(res.files[2].c_str())))
 -              {
 -                      if (!res.pTempPathContext)
 -                      {
 -                              res.pTempPathContext = new CTempPathContext;
 -                              for (int index = 0; index < res.files.GetSize(); index++)
 -                                      res.pTempPathContext->m_strDisplayRoot[index] = res.files[index];
 -                      }
 -                      path = env_GetTempChildPath();
 -                      do
 -                      {
 -                              if (FAILED(piHandler->DeCompressArchive(hWnd, res.files[2].c_str(), path.c_str())))
 -                                      break;;
 -                              if (res.files[2].find(path) == 0)
 -                              {
 -                                      VERIFY(::DeleteFile(res.files[2].c_str()) || (LogErrorString(string_format(_T("DeleteFile(%s) failed"), res.files[2].c_str())), false));
 -                              }
 -                              BSTR pTmp = piHandler->GetDefaultName(hWnd, res.files[1].c_str());
 -                              res.files[2] = OLE2T(pTmp);
 -                              SysFreeString(pTmp);
 -                              res.files[2].insert(0, _T("\\"));
 -                              res.files[2].insert(0, path);
 -                      } while (piHandler = ArchiveGuessFormat(res.files[2].c_str()));
 -                      res.files[2] = path;
 -              }
 -              if (res.files[1].empty())
 -              {
 -                      // assume Perry style patch
 -                      res.files[1] = path;
 -                      res.files[0] += _T("\\ORIGINAL");
 -                      res.files[1] += _T("\\ALTERED");
 -                      if (!PathFileExists(res.files[0].c_str()) || !PathFileExists(res.files[1].c_str()))
 -                      {
 -                              // not a Perry style patch: diff with itself...
 -                              res.files[0] = res.files[1] = path;
 -                      }
 -                      else
 -                      {
 -                              res.pTempPathContext->m_strDisplayRoot[0] += _T("\\ORIGINAL");
 -                              res.pTempPathContext->m_strDisplayRoot[1] += _T("\\ALTERED");
 -                      }
 -              }
 -      }
 -      catch (CException *e)
 -      {
 -              e->ReportError(MB_ICONSTOP);
 -              e->Delete();
 -      }
 -      return res;
 -}
 -
 +/////////////////////////////////////////////////////////////////////////////\r
 +//    WinMerge:  an interactive diff/merge utility\r
 +//    Copyright (C) 1997-2000  Thingamahoochie Software\r
 +//    Author: Dean Grimm\r
 +//\r
 +//    This program is free software; you can redistribute it and/or modify\r
 +//    it under the terms of the GNU General Public License as published by\r
 +//    the Free Software Foundation; either version 2 of the License, or\r
 +//    (at your option) any later version.\r
 +//\r
 +//    This program is distributed in the hope that it will be useful,\r
 +//    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 +//    GNU General Public License for more details.\r
 +//\r
 +//    You should have received a copy of the GNU General Public License\r
 +//    along with this program; if not, write to the Free Software\r
 +//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
 +//\r
 +/////////////////////////////////////////////////////////////////////////////\r
 +\r
 +/* 7zCommon.cpp: Implement 7z related classes and functions\r
 + * Copyright (c) 2003 Jochen Tucht\r
 + *\r
 + * Remarks:   Different versions of 7-Zip are interfaced through specific\r
 + *                    versions of Merge7z (Merge7z311.dll, Merge7z312.dll, etc.)\r
 + *                    WinMerge can either use an installed copy of the 7-Zip software,\r
 + *                    or fallback to a local set of 7-Zip DLLs, which are to be included\r
 + *                    in the WinMerge binary distribution.\r
 + *\r
 + *                    Fallback policies are as follows:\r
 + *\r
 + *                    1. Detect 7-Zip version installed (XXX).\r
 + *                    2. If there is a Merge7zXXX.dll, be happy to use it\r
 + *                    3. Detect 7-Zip version from WinMerge distribution (YYY).\r
 + *                    4. If there is a Merge7zYYY.dll, be happy to use it.\r
 + *                    5. Sorry, no way.\r
 + *\r
 + *                    These rules can be customized by setting a registry variable\r
 + *                    *Merge7z/Enable* of type DWORD to one of the following values:\r
 + *\r
 + *                    0 - Entirely disable 7-Zip integration.\r
 + *                    1 - Use installed 7-Zip if present. Otherwise, use local 7-Zip.\r
 + *                    2 - Always use local 7-Zip.\r
 + *\r
 +\r
 +Please mind 2. a) of the GNU General Public License, and log your changes below.\r
 +\r
 +DATE:         BY:                                     DESCRIPTION:\r
 +==========    ==================      ================================================\r
 +2003-12-09    Jochen Tucht            Created\r
 +2003-12-16    Jochen Tucht            Properly generate .tar.gz and .tar.bz2\r
 +2003-12-16    Jochen Tucht            Obtain long path to temporary folder\r
 +2004-01-20    Jochen Tucht            Complain only once if Merge7z*.dll is missing\r
 +2004-01-25    Jochen Tucht            Fix bad default for OPENFILENAME::nFilterIndex\r
 +2004-03-15    Jochen Tucht            Fix Visual Studio 2003 build issue\r
 +2004-04-13    Jochen Tucht            Avoid StrNCat to get away with shlwapi 4.70\r
 +2004-08-25    Jochen Tucht            More explicit error message\r
 +2004-10-17    Jochen Tucht            Leave decision whether to recurse into folders\r
 +                                                              to enumerator (Mask.Recurse)\r
 +2004-11-03    Jochen Tucht            FIX [1048997] as proposed by Kimmo 2004-11-02\r
 +2005-01-15    Jochen Tucht            Read 7-Zip version from 7zip_pad.xml\r
 +                                                              Set Merge7z UI language if DllBuild_Merge7z >= 9\r
 +2005-01-22    Jochen Tucht            Better explain what's present/missing/outdated\r
 +2005-02-05    Jochen Tucht            Fall back to IDD_MERGE7ZMISMATCH template from\r
 +                                                              .exe if .lang file isn't up to date.\r
 +2005-02-26    Jochen Tucht            Add download link to error message\r
 +2005-02-26    Jochen Tucht            Use WinAPI to obtain ISO language/region codes\r
 +2005-02-27    Jochen Tucht            FIX [1152375]\r
 +2005-04-24    Kimmo Varis                     Don't use DiffContext exported from DirView\r
 +2005-06-08    Kimmo Varis                     Use DIFFITEM, not reference to it (hopefully only\r
 +                                                              temporarily, to sort out new directory compare)\r
 +2005-06-22    Jochen Tucht            Change recommended version of 7-Zip to 4.20\r
 +                                                              Remove noise from Nagbox\r
 +2005-07-03    Jochen Tucht            DIFFITEM has changed due to RFE [ 1205516 ]\r
 +2005-07-04    Jochen Tucht            New global ArchiveGuessFormat() checks for\r
 +                                                              formats to be handled by external command line\r
 +                                                              tools. These take precedence over Merge7z\r
 +                                                              internal handlers.\r
 +2005-07-05    Jochen Tucht            Move to Merge7z::Format::GetDefaultName() to\r
 +                                                              build intermediate filenames for multi-step\r
 +                                                              compression.\r
 +2005-07-15    Jochen Tucht            Remove external command line tool integration\r
 +                                                              for now. Rethink about it after 2.4 branch.\r
 +2005-08-20    Jochen Tucht            Option to guess archive format by signature\r
 +                                                              Map extensions through ExternalArchiveFormat.ini\r
 +2005-08-23    Jochen Tucht            Option to entirely disable 7-Zip integration\r
 +2007-01-04    Kimmo Varis                     Convert using COptionsMgr for options.\r
 +2007-06-16    Jochen Neubeck          FIX [1723263] "Zip --> Both" operation...\r
 +2007-12-22    Jochen Neubeck          Fix Merge7z UI lang for new translation system\r
 +                                                              Change recommended version of 7-Zip to 4.57\r
 +2010-05-16    Jochen Neubeck          Read 7-Zip version from 7z.dll (which has long\r
 +                                                              ago replaced the various format and codec DLLs)\r
 +                                                              Change recommended version of 7-Zip to 4.65\r
 +*/\r
 +\r
- // ID line follows -- this is updated by SVN\r
- // $Id: 7zCommon.cpp 7169 2010-05-16 14:44:19Z jtuc $\r
 +\r
 +#include "stdafx.h"\r
 +#include "7zCommon.h"\r
 +#include <afxinet.h>\r
 +#include <shlwapi.h>\r
 +#include "OptionsDef.h"\r
 +#include "OptionsMgr.h"\r
 +#include "Merge.h"            // DirDocFilter theApp GetOptionsMgr()\r
 +#include "resource.h"\r
 +#include "DirView.h"\r
 +#include "DirDoc.h"\r
 +#include "DirActions.h"\r
 +//#include "ExternalArchiveFormat.h"\r
 +#include "version.h"\r
 +#include "paths.h"\r
 +#include "Environment.h"\r
 +#include "Merge7zFormatRegister.h"\r
 +\r
 +#ifdef _DEBUG\r
 +#define new DEBUG_NEW\r
 +#undef THIS_FILE\r
 +static char THIS_FILE[] = __FILE__;\r
 +#endif\r
 +\r
 +/**\r
 + * @brief Proxy for Merge7z\r
 + */\r
 +static __declspec(thread) Merge7z::Proxy m_Merge7z =\r
 +{\r
 +      { 0, 0, DllBuild_Merge7z, },\r
 +      "Merge7z%u%02u"DECORATE_U".dll",\r
 +      "Merge7z",\r
 +      NULL\r
 +};\r
 +\r
 +std::vector<Merge7z::Format *(*)(const String& path)> Merge7zFormatRegister::optionalFormats;\r
 +\r
 +/**\r
 + * @brief assign BSTR to String, and return BSTR for optional SysFreeString()\r
 + */\r
 +inline BSTR Assign(CString &dst, BSTR src)\r
 +{\r
 +      dst = src;\r
 +      return src;\r
 +}\r
 +\r
 +bool IsArchiveFile(const String& pszFile)\r
 +{\r
 +      try {\r
 +              Merge7z::Format *piHandler = ArchiveGuessFormat(pszFile);\r
 +              if (piHandler)\r
 +                      return TRUE;\r
 +              else\r
 +                      return FALSE;\r
 +      }\r
 +      catch (CException *e)\r
 +      {\r
 +              e->Delete();\r
 +              return FALSE;\r
 +      }\r
 +      return FALSE;\r
 +}\r
 +\r
 +/**\r
 + * @brief Wrap Merge7z::GuessFormat() to allow for some customizing:\r
 + * - Check if 7-Zip integration is enabled.\r
 + * - Check for filename extension mappings.\r
 + */\r
 +Merge7z::Format *ArchiveGuessFormat(const String& path)\r
 +{\r
 +      if (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE) == 0)\r
 +              return NULL;\r
 +      if (paths_IsDirectory(path))\r
 +              return NULL;\r
 +      String path2(path);\r
 +      // Map extensions through ExternalArchiveFormat.ini\r
 +      static TCHAR null[] = _T("");\r
 +      static const TCHAR section[] = _T("extensions");\r
 +      String entry = paths_FindExtension(path);\r
 +      TCHAR value[20];\r
 +      static LPCTSTR filename = NULL;\r
 +      if (filename == NULL)\r
 +      {\r
 +              TCHAR cPath[INTERNET_MAX_PATH_LENGTH];\r
 +              DWORD cchPath = SearchPath(NULL, _T("ExternalArchiveFormat.ini"), NULL,\r
 +                      INTERNET_MAX_PATH_LENGTH, cPath, NULL);\r
 +              filename = cchPath && cchPath < INTERNET_MAX_PATH_LENGTH ? StrDup(cPath) : null;\r
 +      }\r
 +      if (*filename &&\r
 +              GetPrivateProfileString(section, entry.c_str(), null, value, 20, filename) &&\r
 +              *value == '.')\r
 +      {\r
 +              // Remove end-of-line comments (in string returned from GetPrivateProfileString)\r
 +              // that is, remove semicolon & whatever follows it\r
 +              if (LPTSTR p = StrChr(value, ';'))\r
 +              {\r
 +                      *p = '\0';\r
 +                      StrTrim(value, _T(" \t"));\r
 +              }\r
 +              path2 = value;\r
 +      }\r
 +\r
 +      // PATCH [ 1229867 ] RFE [ 1205516 ], RFE [ 887948 ], and other issues\r
 +      // command line integration portion is not yet applied\r
 +      // so following code not yet valid, so temporarily commented out\r
 +      // Look for command line tool first\r
 +      /*Merge7z::Format *pFormat;\r
 +      if (CExternalArchiveFormat::GuessFormat(path, pFormat))\r
 +      {\r
 +              return pFormat;\r
 +      }*/\r
 +      // Default to Merge7z*.dll\r
 +\r
 +      try\r
 +      {\r
 +              Merge7z::Format *pFormat = m_Merge7z->GuessFormat(path2.c_str());\r
 +              if (!pFormat)\r
 +                      pFormat = Merge7zFormatRegister::GuessFormat(path2);\r
 +              return pFormat;\r
 +      }\r
 +      catch (...)\r
 +      {\r
 +              Merge7z::Format *pFormat = Merge7zFormatRegister::GuessFormat(path2);\r
 +              if (pFormat)\r
 +                      return pFormat;\r
 +              throw;\r
 +      }\r
 +}\r
 +\r
 +/**\r
 + * @brief Self-initializing raw C character buffer class.\r
 + */\r
 +template<class TYPE, size_t SIZE> struct CRawString\r
 +{\r
 +      enum { Size = SIZE };\r
 +      TYPE Data[SIZE];\r
 +      CRawString()\r
 +      {\r
 +              Data[0] = 0;\r
 +      }\r
 +};\r
 +\r
 +/**\r
 + * @brief Exception class for more explicit error message.\r
 + */\r
 +class C7ZipMismatchException : public CException\r
 +{\r
 +public:\r
 +      C7ZipMismatchException(DWORD dwVer7zInstalled, DWORD dwVer7zLocal, CException *pCause)\r
 +      {\r
 +              m_dwVer7zInstalled = dwVer7zInstalled;\r
 +              m_dwVer7zLocal = dwVer7zLocal;\r
 +              m_pCause = pCause;\r
 +      }\r
 +      ~C7ZipMismatchException()\r
 +      {\r
 +              if (m_pCause)\r
 +                      m_pCause->Delete();\r
 +      }\r
 +      virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);\r
 +protected:\r
 +      DWORD m_dwVer7zInstalled;\r
 +      DWORD m_dwVer7zLocal;\r
 +      CException *m_pCause;\r
 +      BOOL m_bShowAllways;\r
 +      static const DWORD m_dwVer7zRecommended;\r
 +      static const TCHAR m_strRegistryKey[];\r
 +      static const TCHAR m_strDownloadURL[];\r
 +      static INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);\r
 +      static DWORD FormatVersion(LPTSTR, LPTSTR, DWORD);\r
 +};\r
 +\r
 +/**\r
 + * @brief Recommended version of 7-Zip.\r
 + */\r
 +const DWORD C7ZipMismatchException::m_dwVer7zRecommended = DWORD MAKELONG(65,4);\r
 +\r
 +/**\r
 + * @brief Registry key for C7ZipMismatchException's ReportError() popup.\r
 + */\r
 +const TCHAR C7ZipMismatchException::m_strRegistryKey[] = _T("7ZipMismatch");\r
 +\r
 +/**\r
 + * @brief Download URL for C7ZipMismatchException's ReportError() popup.\r
 + */\r
 +const TCHAR C7ZipMismatchException::m_strDownloadURL[] = _T("https://sourceforge.net/project/showfiles.php?group_id=13216&package_id=143957");\r
 +\r
 +/**\r
 + * @brief Retrieve build number of given DLL.\r
 + */\r
 +static DWORD NTAPI GetDllBuild(LPCTSTR cPath)\r
 +{\r
 +      HMODULE hModule = LoadLibrary(cPath);\r
 +      DLLVERSIONINFO dvi;\r
 +      dvi.cbSize = sizeof dvi;\r
 +      dvi.dwBuildNumber = ~0UL;\r
 +      if (hModule)\r
 +      {\r
 +              dvi.dwBuildNumber = 0UL;\r
 +              DLLGETVERSIONPROC DllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hModule, "DllGetVersion");\r
 +              if (DllGetVersion)\r
 +              {\r
 +                      DllGetVersion(&dvi);\r
 +              }\r
 +              FreeLibrary(hModule);\r
 +      }\r
 +      return dvi.dwBuildNumber;\r
 +}\r
 +\r
 +/**\r
 + * @brief Format Merge7z version number and plugin name, and retrieve DllBuild.\r
 + */\r
 +DWORD C7ZipMismatchException::FormatVersion(LPTSTR pcVersion, LPTSTR pcPluginName, DWORD dwVersion)\r
 +{\r
 +      *pcVersion = '\0';\r
 +      *pcPluginName = '\0';\r
 +      if (dwVersion)\r
 +      {\r
 +              wsprintf\r
 +              (\r
 +                      pcVersion, _T("%u.%02u"),\r
 +                      UINT HIWORD(dwVersion),\r
 +                      UINT LOWORD(dwVersion)\r
 +              );\r
 +              wsprintf\r
 +              (\r
 +                      pcPluginName,\r
 +                      sizeof(TCHAR) == 1 ? _T("Merge7z%u%02u.dll") : _T("Merge7z%u%02uU.dll"),\r
 +                      UINT HIWORD(dwVersion),\r
 +                      UINT LOWORD(dwVersion)\r
 +              );\r
 +      }\r
 +      return GetDllBuild(pcPluginName);\r
 +}\r
 +\r
 +/**\r
 + * @brief Populate ListBox with names/revisions of DLLs matching given pattern.\r
 + */\r
 +static void NTAPI DlgDirListDLLs(HWND hWnd, LPTSTR cPattern, int nIDListBox)\r
 +{\r
 +      HDC hDC = GetDC(hWnd);\r
 +      HFONT hFont = (HFONT)SendDlgItemMessage(hWnd, nIDListBox, WM_GETFONT, 0, 0);\r
 +      int cxView = (int)SendDlgItemMessage(hWnd, nIDListBox, LB_GETHORIZONTALEXTENT, 0, 0) - 8;\r
 +      HGDIOBJ hObject = SelectObject(hDC, hFont);\r
 +      WIN32_FIND_DATA ff;\r
 +      HANDLE h = FindFirstFile(cPattern, &ff);\r
 +      if (h != INVALID_HANDLE_VALUE)\r
 +      {\r
 +              do\r
 +              {\r
 +                      PathRemoveFileSpec(cPattern);\r
 +                      PathAppend(cPattern, ff.cFileName);\r
 +                      wsprintf(ff.cFileName, _T(" (dllbuild %04u)"), GetDllBuild(cPattern));\r
 +                      lstrcat(cPattern, ff.cFileName);\r
 +                      int cxText = (int)(WORD)GetTabbedTextExtent(hDC, cPattern, lstrlen(cPattern), 0, 0);\r
 +                      if (cxView < cxText)\r
 +                              cxView = cxText;\r
 +                      SendDlgItemMessage(hWnd, nIDListBox, LB_ADDSTRING, 0, (LPARAM)cPattern);\r
 +              } while (FindNextFile(h, &ff));\r
 +              FindClose(h);\r
 +      }\r
 +      SelectObject(hDC, hObject);\r
 +      ReleaseDC(hWnd, hDC);\r
 +      SendDlgItemMessage(hWnd, nIDListBox, LB_SETHORIZONTALEXTENT, cxView + 8, 0);\r
 +}\r
 +\r
 +/**\r
 + * @brief OwnerDraw states from recent SDK.\r
 + */\r
 +#define ODS_NOACCEL         0x0100\r
 +#define ODS_NOFOCUSRECT     0x0200\r
 +\r
 +/**\r
 + * @brief WM_DRAWITEM notification handlers.\r
 + */\r
 +struct CDrawItemStruct : DRAWITEMSTRUCT\r
 +{\r
 +      typedef CDrawItemStruct *From;\r
 +      void DrawWebLinkButton();\r
 +};\r
 +\r
 +void CDrawItemStruct::DrawWebLinkButton()\r
 +{\r
 +      CRawString<TCHAR,INTERNET_MAX_PATH_LENGTH> cText;\r
 +      int cchText = ::GetWindowText(hwndItem, cText.Data, cText.Size);\r
 +      COLORREF clrText = RGB(0,0,255);\r
 +      if (::GetWindowLong(hwndItem, GWL_STYLE) & BS_LEFTTEXT)\r
 +      {\r
 +              clrText = RGB(128,0,128);\r
 +      }\r
 +      RECT rcText = rcItem;\r
 +      ::DrawText(hDC, cText.Data, cchText, &rcText, DT_LEFT|DT_CALCRECT);\r
 +      ::OffsetRect(&rcText, 1, 0);\r
 +      rcItem.right = rcText.right + 1;\r
 +      rcItem.bottom = rcText.bottom + 1;\r
 +      switch (itemAction)\r
 +      {\r
 +      case ODA_DRAWENTIRE:\r
 +              ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcItem, 0, 0, 0);\r
 +              ::SetBkMode(hDC, TRANSPARENT);\r
 +              ::SetTextColor(hDC, clrText);\r
 +              ::DrawText(hDC, cText.Data, cchText, &rcText, DT_LEFT);\r
 +              rcText.top = rcText.bottom - 1;\r
 +              ::SetBkColor(hDC, clrText);\r
 +              ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcText, 0, 0, 0);\r
 +              if (itemState & ODS_FOCUS)\r
 +              {\r
 +              case ODA_FOCUS:\r
 +                      if (!(itemState & ODS_NOFOCUSRECT))\r
 +                      {\r
 +                              ::SetTextColor(hDC, 0);\r
 +                              ::SetBkColor(hDC, RGB(255,255,255));\r
 +                              ::SetBkMode(hDC, OPAQUE);\r
 +                              DrawFocusRect(hDC, &rcItem);\r
 +                      }\r
 +              }\r
 +              break;\r
 +      }\r
 +}\r
 +\r
 +/**\r
 + * @brief Load a cursor from COMCTL32.DLL.\r
 + */\r
 +HCURSOR NTAPI CommCtrl_LoadCursor(LPCTSTR lpCursorName)\r
 +{\r
 +      HMODULE hModule = GetModuleHandle(_T("COMCTL32.DLL"));\r
 +      return hModule ? LoadCursor(hModule, lpCursorName) : NULL;\r
 +}\r
 +\r
 +/**\r
 + * @brief DLGPROC for C7ZipMismatchException's ReportError() popup.\r
 + */\r
 +INT_PTR CALLBACK C7ZipMismatchException::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
 +{\r
 +      switch (uMsg)\r
 +      {\r
 +              case WM_INITDIALOG:\r
 +              {\r
 +                      theApp.TranslateDialog(hWnd);\r
 +                      if (GetDlgItem(hWnd, 9001) == NULL)\r
 +                      {\r
 +                              // Dialog template isn't up to date. Give it a second chance.\r
 +                              EndDialog(hWnd, -1);\r
 +                              return FALSE;\r
 +                      }\r
 +                      C7ZipMismatchException *pThis = (C7ZipMismatchException *)lParam;\r
 +                      CRawString<TCHAR,2600> cText;\r
 +                      CRawString<TCHAR,80> cPresent, cMissing, cOutdated, cNone, cPlugin;\r
 +                      if (pThis->m_pCause)\r
 +                      {\r
 +                              pThis->m_pCause->GetErrorMessage(cText.Data, cText.Size);\r
 +                              SetDlgItemText(hWnd, 107, cText.Data);\r
 +                      }\r
 +                      else\r
 +                      {\r
 +                              GetDlgItemText(hWnd, 107, cText.Data, cText.Size);\r
 +                              switch (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE))\r
 +                              {\r
 +                              case 0:\r
 +                                      lstrcat(cText.Data, _("\nNote: 7-Zip integration is disabled in WinMerge settings.").c_str());\r
 +                                      break;\r
 +                              case 2:\r
 +                                      lstrcat(cText.Data, _("\nNote: 7-Zip integration is restricted to standalone operation in WinMerge settings.").c_str());\r
 +                                      break;\r
 +                              }\r
 +                              SetDlgItemText(hWnd, 107, cText.Data);\r
 +                      }\r
 +                      GetDlgItemText(hWnd, 112, cPresent.Data, cPresent.Size);\r
 +                      GetDlgItemText(hWnd, 122, cMissing.Data, cMissing.Size);\r
 +                      GetDlgItemText(hWnd, 132, cOutdated.Data, cOutdated.Size);\r
 +                      GetDlgItemText(hWnd, 120, cNone.Data, cNone.Size);\r
 +                      GetDlgItemText(hWnd, 102, cPlugin.Data, cPlugin.Size);\r
 +                      wsprintf(cText.Data, cPlugin.Data, DllBuild_Merge7z);\r
 +                      SetDlgItemText(hWnd, 102, cText.Data);\r
 +                      SetDlgItemText\r
 +                      (\r
 +                              hWnd, 109,\r
 +                              (\r
 +                                      pThis->m_dwVer7zRecommended == pThis->m_dwVer7zInstalled\r
 +                              ||      pThis->m_dwVer7zRecommended == pThis->m_dwVer7zLocal\r
 +                              ) ? cPresent.Data : cMissing.Data\r
 +                      );\r
 +                      DWORD dwDllBuild = FormatVersion(cText.Data, cPlugin.Data, pThis->m_dwVer7zRecommended);\r
 +                      SetDlgItemText(hWnd, 110, *cText.Data ? cText.Data : cNone.Data);\r
 +                      SetDlgItemText(hWnd, 111, cPlugin.Data);\r
 +                      SetDlgItemText(hWnd, 112, *cPlugin.Data == '\0' ? cPlugin.Data :\r
 +                              dwDllBuild == ~0 ? cMissing.Data : dwDllBuild < DllBuild_Merge7z ? cOutdated.Data : cPresent.Data);\r
 +                      dwDllBuild = FormatVersion(cText.Data, cPlugin.Data, pThis->m_dwVer7zInstalled);\r
 +                      SetDlgItemText(hWnd, 120, *cText.Data ? cText.Data : cNone.Data);\r
 +                      SetDlgItemText(hWnd, 121, cPlugin.Data);\r
 +                      SetDlgItemText(hWnd, 122, *cPlugin.Data == '\0' ? cPlugin.Data :\r
 +                              dwDllBuild == ~0 ? cMissing.Data : dwDllBuild < DllBuild_Merge7z ? cOutdated.Data : cPresent.Data);\r
 +                      dwDllBuild = FormatVersion(cText.Data, cPlugin.Data, pThis->m_dwVer7zLocal);\r
 +                      SetDlgItemText(hWnd, 130, *cText.Data ? cText.Data : cNone.Data);\r
 +                      SetDlgItemText(hWnd, 131, cPlugin.Data);\r
 +                      SetDlgItemText(hWnd, 132, *cPlugin.Data == '\0' ? cPlugin.Data :\r
 +                              dwDllBuild == ~0 ? cMissing.Data : dwDllBuild < DllBuild_Merge7z ? cOutdated.Data : cPresent.Data);\r
 +                      GetModuleFileName(0, cText.Data, MAX_PATH);\r
 +                      PathRemoveFileSpec(cText.Data);\r
 +                      PathAppend(cText.Data, _T("Merge7z*.dll"));\r
 +                      DlgDirListDLLs(hWnd, cText.Data, 105);\r
 +                      if (DWORD cchPath = GetEnvironmentVariable(_T("path"), 0, 0))\r
 +                      {\r
 +                              static const TCHAR cSep[] = _T(";");\r
 +                              LPTSTR pchPath = new TCHAR[cchPath];\r
 +                              GetEnvironmentVariable(_T("PATH"), pchPath, cchPath);\r
 +                              LPTSTR pchItem = pchPath;\r
 +                              while (int cchItem = StrCSpn(pchItem += StrSpn(pchItem, cSep), cSep))\r
 +                              {\r
 +                                      if (cchItem < MAX_PATH)\r
 +                                      {\r
 +                                              CopyMemory(cText.Data, pchItem, cchItem*sizeof*pchItem);\r
 +                                              cText.Data[cchItem] = 0;\r
 +                                              PathAppend(cText.Data, _T("Merge7z*.dll"));\r
 +                                              DlgDirListDLLs(hWnd, cText.Data, 105);\r
 +                                      }\r
 +                                      pchItem += cchItem;\r
 +                              }\r
 +                              delete[] pchPath;\r
 +                      }\r
 +                      if (SendDlgItemMessage(hWnd, 105, LB_GETCOUNT, 0, 0) == 0)\r
 +                      {\r
 +                              SendDlgItemMessage(hWnd, 105, LB_ADDSTRING, 0, (LPARAM) cNone.Data);\r
 +                      }\r
 +                      HICON hIcon = LoadIcon(0, IDI_EXCLAMATION);\r
 +                      SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);\r
 +                      SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);\r
 +                      if (pThis->m_bShowAllways)\r
 +                      {\r
 +                              ShowWindow(GetDlgItem(hWnd, 106), SW_HIDE);\r
 +                      }\r
 +              } return TRUE;\r
 +              case WM_DRAWITEM:\r
 +              {\r
 +                      switch (wParam)\r
 +                      {\r
 +                      case 108:\r
 +                              CDrawItemStruct::From(lParam)->DrawWebLinkButton();\r
 +                              break;\r
 +                      }\r
 +              } return TRUE;\r
 +              case WM_SETCURSOR:\r
 +              {\r
 +                      HCURSOR hCursor = 0;\r
 +                      switch (GetDlgCtrlID((HWND)wParam))\r
 +                      {\r
 +                      case 108:\r
 +                              hCursor = CommCtrl_LoadCursor(MAKEINTRESOURCE(108));\r
 +                              break;\r
 +                      }\r
 +                      if (hCursor)\r
 +                      {\r
 +                              SetCursor(hCursor);\r
 +                              SetWindowLongPtr(hWnd, DWLP_MSGRESULT, 1);\r
 +                              return TRUE;\r
 +                      }\r
 +              } return FALSE;\r
 +              case WM_COMMAND:\r
 +              {\r
 +                      switch (wParam)\r
 +                      {\r
 +                              case IDOK:\r
 +                              case IDCANCEL:\r
 +                              {\r
 +                                      LRESULT nDontShowAgain = SendDlgItemMessage(hWnd, 106, BM_GETCHECK, 0, 0);\r
 +                                      EndDialog(hWnd, MAKEWORD(IDOK, nDontShowAgain));\r
 +                              } break;\r
 +                              case 108:\r
 +                              {\r
 +                                      HINSTANCE h = ShellExecute(hWnd, _T("open"), m_strDownloadURL, 0, 0, SW_SHOWNORMAL);\r
 +                                      if ((UINT)h > 32)\r
 +                                      {\r
 +                                              LONG lStyle = ::GetWindowLong((HWND)lParam, GWL_STYLE);\r
 +                                              ::SetWindowLong((HWND)lParam, GWL_STYLE, lStyle|BS_LEFTTEXT);\r
 +                                              ::InvalidateRect((HWND)lParam, 0, TRUE);\r
 +                                      }\r
 +                                      else\r
 +                                      {\r
 +                                              MessageBeep(0);\r
 +                                      }\r
 +                              } break;\r
 +                      }\r
 +              } return TRUE;\r
 +      }\r
 +      return FALSE;\r
 +}\r
 +\r
 +/**\r
 + * @brief Tell user what went wrong and how she can help.\r
 + */\r
 +int C7ZipMismatchException::ReportError(UINT nType, UINT nMessageID)\r
 +{\r
 +      UINT_PTR response = -1;\r
 +      m_bShowAllways = nMessageID;\r
 +      if (!m_bShowAllways)\r
 +      {\r
 +              // Suppress error message in case 7-Zip is not installed.\r
 +              response =\r
 +              (\r
 +                      m_dwVer7zInstalled || m_dwVer7zLocal\r
 +              ?       (INT_PTR)(int)theApp.GetProfileInt(REGISTRY_SECTION_MESSAGEBOX, m_strRegistryKey, -1)\r
 +              :       IDOK\r
 +              );\r
 +      }\r
 +      if (response == -1)\r
 +      {\r
 +              HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();\r
 +              response = DialogBoxParam(AfxGetResourceHandle(), MAKEINTRESOURCE(IDD_MERGE7ZMISMATCH), hwndOwner, DlgProc, (LPARAM)this);\r
 +              if (response == -1)\r
 +              {\r
 +                      response = DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_MERGE7ZMISMATCH), hwndOwner, DlgProc, (LPARAM)this);\r
 +                      ASSERT(response != -1);\r
 +              }\r
 +              if (HIBYTE(response) == 1)\r
 +              {\r
 +                      theApp.WriteProfileInt(REGISTRY_SECTION_MESSAGEBOX, m_strRegistryKey, response = int LOBYTE(response));\r
 +              }\r
 +      }\r
 +      return response;\r
 +}\r
 +\r
 +/**\r
 + * @brief Check whether archive support is available.\r
 + */\r
 +int NTAPI HasZipSupport()\r
 +{\r
 +      static int HasZipSupport = -1;\r
 +      if (HasZipSupport == -1)\r
 +      {\r
 +              try\r
 +              {\r
 +                      m_Merge7z.operator->();\r
 +                      HasZipSupport = 1;\r
 +              }\r
 +              catch (CException *e)\r
 +              {\r
 +                      e->Delete();\r
 +                      HasZipSupport = 0;\r
 +              }\r
 +      }\r
 +      return HasZipSupport;\r
 +}\r
 +\r
 +/**\r
 + * @brief Tell user why archive support is not available.\r
 + */\r
 +void NTAPI Recall7ZipMismatchError()\r
 +{\r
 +      try\r
 +      {\r
 +              m_Merge7z.operator->();\r
 +      }\r
 +      catch (CException *e)\r
 +      {\r
 +              e->ReportError(MB_ICONEXCLAMATION, TRUE);\r
 +              e->Delete();\r
 +      }\r
 +}\r
 +\r
 +/**\r
 + * @brief Delete head of temp path context list, and return its parent context.\r
 + */\r
 +CTempPathContext *CTempPathContext::DeleteHead()\r
 +{\r
 +      CTempPathContext *pParent = m_pParent;\r
 +      delete this;\r
 +      return pParent;\r
 +}\r
 +\r
 +BOOL NTAPI IsMerge7zEnabled()\r
 +{\r
 +      return AfxGetApp()->GetProfileInt(_T("Merge7z"), _T("Enable"), 0);\r
 +}\r
 +\r
 +/**\r
 + * @brief Return installed or local version of 7-Zip.\r
 + */\r
 +DWORD NTAPI VersionOf7z(BOOL bLocal)\r
 +{\r
 +      TCHAR path[MAX_PATH];\r
 +      if (bLocal)\r
 +      {\r
 +              GetModuleFileName(0, path, sizeof path/sizeof*path);\r
 +              PathRemoveFileSpec(path);\r
 +      }\r
 +      else\r
 +      {\r
 +              static const TCHAR szSubKey[] = _T("Software\\7-Zip");\r
 +              static const TCHAR szValue[] = _T("Path");\r
 +              DWORD type = 0;\r
 +              DWORD size = sizeof path;\r
 +              SHGetValue(HKEY_LOCAL_MACHINE, szSubKey, szValue, &type, path, &size);\r
 +      }\r
 +      PathAppend(path, _T("7z.dll"));\r
 +      unsigned versionMS = 0;\r
 +      unsigned versionLS = 0;\r
 +      CVersionInfo(path).GetFixedFileVersion(versionMS, versionLS);\r
 +      return versionMS;\r
 +}\r
 +\r
 +/**\r
 + * @brief Access dll functions through proxy.\r
 + */\r
 +interface Merge7z *Merge7z::Proxy::operator->()\r
 +{\r
 +      // As long as the Merge7z*.DLL has not yet been loaded, Merge7z\r
 +      // [0] points to the name of the DLL (with placeholders for 7-\r
 +      // Zip major and minor version numbers). Once the DLL has been\r
 +      // loaded successfully, Merge7z[0] is set to NULL, causing the\r
 +      // if to fail on subsequent calls.\r
 +\r
 +      if (const char *format = Merge7z[0])\r
 +      {\r
 +              // Merge7z has not yet been loaded\r
 +\r
 +              char name[MAX_PATH];\r
 +              DWORD flags = ~0;\r
 +              CException *pCause = NULL;\r
 +              switch (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE))\r
 +              {\r
 +              case 1: //Use installed 7-Zip if present. Otherwise, use local 7-Zip.\r
 +                      if (DWORD ver = VersionOf7z(FALSE))\r
 +                      {\r
 +                              flags = Initialize::Default;\r
 +                              try\r
 +                              {\r
 +                                      wsprintfA(name, format, UINT HIWORD(ver), UINT LOWORD(ver));\r
 +                                      Merge7z[0] = name;\r
 +                                      stub.Load();\r
 +                                      break;\r
 +                              }\r
 +                              catch (CException *e)\r
 +                              {\r
 +                                      Merge7z[0] = format;\r
 +                                      pCause = e;\r
 +                              }\r
 +                      }\r
 +              case 2: //Always use local 7-Zip.\r
 +                      if (DWORD ver = VersionOf7z(TRUE))\r
 +                      {\r
 +                              flags = Initialize::Default | Initialize::Local7z;\r
 +                              try\r
 +                              {\r
 +                                      wsprintfA(name, format, UINT HIWORD(ver), UINT LOWORD(ver));\r
 +                                      Merge7z[0] = name;\r
 +                                      stub.Load();\r
 +                                      break;\r
 +                              }\r
 +                              catch (CException *e)\r
 +                              {\r
 +                                      Merge7z[0] = format;\r
 +                                      if (pCause) pCause->Delete();\r
 +                                      pCause = e;\r
 +                              }\r
 +                      }\r
 +              default:\r
 +                      throw new C7ZipMismatchException\r
 +                      (\r
 +                              VersionOf7z(FALSE),\r
 +                              VersionOf7z(TRUE),\r
 +                              pCause\r
 +                      );\r
 +              }\r
 +              LANGID wLangID = (LANGID)GetThreadLocale();\r
 +              flags |= wLangID << 16;\r
 +              if (GetOptionsMgr()->GetBool(OPT_ARCHIVE_PROBETYPE))\r
 +              {\r
 +                      flags |= Initialize::GuessFormatBySignature | Initialize::GuessFormatByExtension;\r
 +              }\r
 +              if (Merge7z[1])\r
 +                      ((interface Merge7z *)Merge7z[1])->Initialize(flags);\r
 +      }\r
 +      return ((interface Merge7z *)Merge7z[1]);\r
 +}\r
 +\r
 +/**\r
 + * @brief Tell Merge7z we are going to enumerate just 1 item.\r
 + */\r
 +UINT SingleItemEnumerator::Open()\r
 +{\r
 +      return 1;\r
 +}\r
 +\r
 +/**\r
 + * @brief Pass information about the item to Merge7z.\r
 + */\r
 +Merge7z::Envelope *SingleItemEnumerator::Enum(Item &item)\r
 +{\r
 +      item.Mask.Item = item.Mask.Name|item.Mask.FullPath|item.Mask.Recurse;\r
 +      item.Name = Name;\r
 +      item.FullPath = FullPath;\r
 +      return 0;\r
 +}\r
 +\r
 +/**\r
 + * @brief SingleFileEnumerator constructor.\r
 + */\r
 +SingleItemEnumerator::SingleItemEnumerator(LPCTSTR path, LPCTSTR FullPath, LPCTSTR Name)\r
 +: FullPath(FullPath)\r
 +, Name(Name)\r
 +{\r
 +}\r
 +\r
 +/**\r
 + * @brief Construct a DirItemEnumerator.\r
 + *\r
 + * Argument *nFlags* controls operation as follows:\r
 + * LVNI_ALL:          Enumerate all items.\r
 + * LVNI_SELECTED:     Enumerate selected items only.\r
 + * Original:          Set folder prefix for first iteration to "original"\r
 + * Altered:                   Set folder prefix for second iteration to "altered"\r
 + * BalanceFolders:    Ensure that all nonempty folders on either side have a\r
 + *                                    corresponding folder on the other side, even if it is\r
 + *                                    empty (DirScan doesn't recurse into folders which\r
 + *                                    appear only on one side).\r
 + * DiffsOnly:         Enumerate diffs only.\r
 + */\r
 +DirItemEnumerator::DirItemEnumerator(CDirView *pView, int nFlags)\r
 +: m_pView(pView)\r
 +, m_nFlags(nFlags)\r
 +{\r
 +      if (m_nFlags & Original)\r
 +      {\r
 +              m_rgFolderPrefix.push_back(_T("original"));\r
 +      }\r
 +      if (m_nFlags & Altered)\r
 +      {\r
 +              m_rgFolderPrefix.push_back(_T("altered"));\r
 +      }\r
 +      if (m_nFlags & BalanceFolders)\r
 +      {\r
 +              const CDiffContext& ctxt = pView->GetDiffContext();\r
 +              // Collect implied folders\r
 +              for (UINT i = Open() ; i-- ; )\r
 +              {\r
 +                      const DIFFITEM &di = Next();\r
 +                      if ((m_nFlags & DiffsOnly) && !IsItemNavigableDiff(ctxt, di))\r
 +                      {\r
 +                              continue;\r
 +                      }\r
 +                      // Enumerating items\r
 +                      if (di.diffcode.exists(m_index))\r
 +                      {\r
 +                              // Item is present on right side, i.e. folder is implied\r
 +                              m_rgImpliedFolders[m_index][di.diffFileInfo[m_index].path.get()] = PVOID(1);\r
 +                      }\r
 +              }\r
 +      }\r
 +}\r
 +\r
 +/**\r
 + * @brief Initialize enumerator, return number of items to be enumerated.\r
 + */\r
 +UINT DirItemEnumerator::Open()\r
 +{\r
 +      m_nIndex = -1;\r
 +      m_curFolderPrefix = m_rgFolderPrefix.begin();\r
 +      m_index = (m_nFlags & Right) != 0 ? 1 : 0;\r
 +      size_t nrgFolderPrefix = m_rgFolderPrefix.size();\r
 +      if (nrgFolderPrefix)\r
 +      {\r
 +              m_strFolderPrefix = *m_curFolderPrefix++;\r
 +      }\r
 +      else\r
 +      {\r
 +              nrgFolderPrefix = 1;\r
 +      }\r
 +      return\r
 +      (\r
 +              m_nFlags & LVNI_SELECTED\r
 +      ?       pView(m_pView)->GetSelectedCount()\r
 +      :       pView(m_pView)->GetItemCount()\r
 +      ) * nrgFolderPrefix;\r
 +}\r
 +\r
 +/**\r
 + * @brief Return next item.\r
 + */\r
 +const DIFFITEM &DirItemEnumerator::Next()\r
 +{\r
 +      enum {nMask = LVNI_FOCUSED|LVNI_SELECTED|LVNI_CUT|LVNI_DROPHILITED};\r
 +      while ((m_nIndex = pView(m_pView)->GetNextItem(m_nIndex, m_nFlags & nMask)) == -1)\r
 +      {\r
 +              m_strFolderPrefix = *m_curFolderPrefix++;\r
 +              m_index = 1;\r
 +      }\r
 +      return m_pView->GetDiffItem(m_nIndex);\r
 +}\r
 +\r
 +/**\r
 + * @brief Pass information about an item to Merge7z.\r
 + *\r
 + * Information is passed through struct Merge7z::DirItemEnumerator::Item.\r
 + * The *mask* member denotes which of the other members contain valid data.\r
 + * If *mask* is zero upon return, which will be the case if Enum() decides to\r
 + * leave the struct untouched, Merge7z will ignore the item.\r
 + * If Enum() allocates temporary storage for string members, it must also\r
 + * allocate an Envelope, providing a Free() method to free the temporary\r
 + * storage, along with the Envelope itself. The Envelope pointer is passed to\r
 + * Merge7z as the return value of the function. It is not meant to be a success\r
 + * indicator, so if no temporary storage is required, it is perfectly alright\r
 + * to return NULL.\r
 + */\r
 +Merge7z::Envelope *DirItemEnumerator::Enum(Item &item)\r
 +{\r
 +      const CDiffContext& ctxt = m_pView->GetDiffContext();\r
 +      const DIFFITEM &di = Next();\r
 +\r
 +      if ((m_nFlags & DiffsOnly) && !IsItemNavigableDiff(ctxt, di))\r
 +      {\r
 +              return 0;\r
 +      }\r
 +\r
 +      bool isSideOnly = !di.diffcode.exists(m_index);\r
 +\r
 +      Envelope *envelope = new Envelope;\r
 +\r
 +      const String &sFilename = di.diffFileInfo[m_index].filename;\r
 +      const String &sSubdir = di.diffFileInfo[m_index].path;\r
 +      if (sSubdir.length())\r
 +              envelope->Name = paths_ConcatPath(sSubdir, sFilename);\r
 +      else\r
 +              envelope->Name = sFilename;\r
 +      envelope->FullPath = paths_ConcatPath(\r
 +                      di.getFilepath(m_index, ctxt.GetNormalizedPath(m_index)),\r
 +                      sFilename);\r
 +\r
 +      UINT32 Recurse = item.Mask.Recurse;\r
 +\r
 +      if (m_nFlags & BalanceFolders)\r
 +      {\r
 +              // Enumerating items on right side\r
 +              if (isSideOnly)\r
 +              {\r
 +                      // Item is missing on right side\r
 +                      PVOID &implied = m_rgImpliedFolders[m_index][di.diffFileInfo[1-m_index].path.get()];\r
 +                      if (!implied)\r
 +                      {\r
 +                              // Folder is not implied by some other file, and has\r
 +                              // not been enumerated so far, so enumerate it now!\r
 +                              envelope->Name = di.diffFileInfo[1-m_index].path;\r
 +                              envelope->FullPath = di.getFilepath(1-m_index, ctxt.GetNormalizedPath(1-m_index));\r
 +                              implied = PVOID(2); // Don't enumerate same folder twice!\r
 +                              isSideOnly = false;\r
 +                              Recurse = 0;\r
 +                      }\r
 +              }\r
 +      }\r
 +\r
 +      if (isSideOnly)\r
 +      {\r
 +              return envelope;\r
 +      }\r
 +\r
 +      if (m_strFolderPrefix.length())\r
 +      {\r
 +              if (envelope->Name.length())\r
 +                      envelope->Name.insert(0, _T("\\"));\r
 +              envelope->Name.insert(0, m_strFolderPrefix);\r
 +      }\r
 +\r
 +      item.Mask.Item = item.Mask.Name|item.Mask.FullPath|item.Mask.CheckIfPresent|Recurse;\r
 +      item.Name = envelope->Name.c_str();\r
 +      item.FullPath = envelope->FullPath.c_str();\r
 +      return envelope;\r
 +}\r
 +\r
 +/**\r
 + * @brief Apply appropriate handlers from left to right.\r
 + */\r
 +bool DirItemEnumerator::MultiStepCompressArchive(LPCTSTR path)\r
 +{\r
 +      DeleteFile(path);\r
 +      Merge7z::Format *piHandler = ArchiveGuessFormat(path);\r
 +      if (piHandler)\r
 +      {\r
 +              HWND hwndOwner = CWnd::GetSafeOwner()->GetSafeHwnd();\r
 +              CString pathIntermediate;\r
 +              SysFreeString(Assign(pathIntermediate, piHandler->GetDefaultName(hwndOwner, path)));\r
 +              String pathPrepend = path;\r
 +              pathPrepend.resize(pathPrepend.rfind('\\') + 1);\r
 +              pathIntermediate.Insert(0, pathPrepend.c_str());\r
 +              bool bDone = MultiStepCompressArchive(pathIntermediate);\r
 +              if (bDone)\r
 +              {\r
 +                      piHandler->CompressArchive(hwndOwner, path,\r
 +                              &SingleItemEnumerator(path, pathIntermediate));\r
 +                      DeleteFile(pathIntermediate);\r
 +              }\r
 +              else\r
 +              {\r
 +                      piHandler->CompressArchive(hwndOwner, path, this);\r
 +              }\r
 +              return true;\r
 +      }\r
 +      return false;\r
 +}\r
 +\r
 +/**\r
 + * @brief Generate archive from DirView items.\r
 + */\r
 +void DirItemEnumerator::CompressArchive(LPCTSTR path)\r
 +{\r
 +      String strPath;\r
 +      if (path == 0)\r
 +      {\r
 +              // No path given, so prompt for path!\r
 +              static const TCHAR _T_Merge7z[] = _T("Merge7z");\r
 +              static const TCHAR _T_FilterIndex[] = _T("FilterIndex");\r
 +              // 7z311 can only write 7z, zip, and tar(.gz|.bz2) archives, so don't\r
 +              // offer other formats here!\r
 +              static const TCHAR _T_Filter[]\r
 +              (\r
 +                      _T("7z|*.7z|")\r
 +                      //_T("z|*.z|")\r
 +                      _T("zip|*.zip|")\r
 +                      _T("jar (zip)|*.jar|")\r
 +                      _T("ear (zip)|*.ear|")\r
 +                      _T("war (zip)|*.war|")\r
 +                      _T("xpi (zip)|*.xpi|")\r
 +                      //_T("rar|*.rar|")\r
 +                      _T("tar|*.tar|")\r
 +                      _T("tar.z|*.tar.z|")\r
 +                      _T("tar.gz|*.tar.gz|")\r
 +                      _T("tar.bz2|*.tar.bz2|")\r
 +                      //_T("tz|*.tz|")\r
 +                      _T("tgz|*.tgz|")\r
 +                      _T("tbz2|*.tbz2|")\r
 +                      //_T("lzh|*.lzh|")\r
 +                      //_T("cab|*.cab|")\r
 +                      //_T("arj|*.arj|")\r
 +                      //_T("deb|*.deb|")\r
 +                      //_T("rpm|*.rpm|")\r
 +                      //_T("cpio|*.cpio|")\r
 +                      //_T("|")\r
 +              );\r
 +              String strFilter; // = CExternalArchiveFormat::GetOpenFileFilterString();\r
 +              strFilter.insert(0, _T_Filter);\r
 +              strFilter += _T("|");\r
 +              CFileDialog dlg\r
 +              (\r
 +                      FALSE,\r
 +                      0,\r
 +                      0,\r
 +                      OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN,\r
 +                      strFilter.c_str()\r
 +              );\r
 +              dlg.m_ofn.nFilterIndex = AfxGetApp()->GetProfileInt(_T_Merge7z, _T_FilterIndex, 1);\r
 +              // Use extension from current filter as default extension:\r
 +              if (int i = dlg.m_ofn.nFilterIndex)\r
 +              {\r
 +                      dlg.m_ofn.lpstrDefExt = dlg.m_ofn.lpstrFilter;\r
 +                      while (*dlg.m_ofn.lpstrDefExt && --i)\r
 +                      {\r
 +                              dlg.m_ofn.lpstrDefExt += lstrlen(dlg.m_ofn.lpstrDefExt) + 1;\r
 +                              dlg.m_ofn.lpstrDefExt += lstrlen(dlg.m_ofn.lpstrDefExt) + 1;\r
 +                      }\r
 +                      if (*dlg.m_ofn.lpstrDefExt)\r
 +                      {\r
 +                              dlg.m_ofn.lpstrDefExt += lstrlen(dlg.m_ofn.lpstrDefExt) + 3;\r
 +                      }\r
 +              }\r
 +              if (dlg.DoModal() == IDOK)\r
 +              {\r
 +                      strPath = dlg.GetPathName();\r
 +                      path = strPath.c_str();\r
 +                      AfxGetApp()->WriteProfileInt(_T_Merge7z, _T_FilterIndex, dlg.m_ofn.nFilterIndex);\r
 +              }\r
 +      }\r
 +      if (path && !MultiStepCompressArchive(path))\r
 +      {\r
 +              LangMessageBox(IDS_UNKNOWN_ARCHIVE_FORMAT, MB_ICONEXCLAMATION);\r
 +      }\r
 +}\r
 +\r
 +\r
 +DecompressResult DecompressArchive(HWND hWnd, const PathContext& files)\r
 +{\r
 +      DecompressResult res(files, NULL, IS_EXISTING_DIR);\r
 +      try\r
 +      {\r
 +              String path;\r
 +              USES_CONVERSION;\r
 +              // Handle archives using 7-zip\r
 +              Merge7z::Format *piHandler;\r
 +              if (piHandler = ArchiveGuessFormat(res.files[0].c_str()))\r
 +              {\r
 +                      res.pTempPathContext = new CTempPathContext;\r
 +                      path = env_GetTempChildPath();\r
 +                      for (int index = 0; index < res.files.GetSize(); index++)\r
 +                              res.pTempPathContext->m_strDisplayRoot[index] = res.files[index];\r
 +                      if (res.files.GetSize() == 2 && res.files[0] == res.files[1])\r
 +                              res.files[1].erase();\r
 +                      do\r
 +                      {\r
 +                              if (FAILED(piHandler->DeCompressArchive(hWnd, res.files[0].c_str(), path.c_str())))\r
 +                                      break;\r
 +                              if (res.files[0].find(path) == 0)\r
 +                              {\r
 +                                      VERIFY(::DeleteFile(res.files[0].c_str()) || (LogErrorString(string_format(_T("DeleteFile(%s) failed"), res.files[0].c_str())), false));\r
 +                              }\r
 +                              BSTR pTmp = piHandler->GetDefaultName(hWnd, res.files[0].c_str());\r
 +                              res.files[0] = OLE2T(pTmp);\r
 +                              SysFreeString(pTmp);\r
 +                              res.files[0].insert(0, _T("\\"));\r
 +                              res.files[0].insert(0, path);\r
 +                      } while (piHandler = ArchiveGuessFormat(res.files[0].c_str()));\r
 +                      res.files[0] = path;\r
 +              }\r
 +              if (!res.files[1].empty() && (piHandler = ArchiveGuessFormat(res.files[1].c_str())))\r
 +              {\r
 +                      if (!res.pTempPathContext)\r
 +                      {\r
 +                              res.pTempPathContext = new CTempPathContext;\r
 +                              for (int index = 0; index < res.files.GetSize(); index++)\r
 +                                      res.pTempPathContext->m_strDisplayRoot[index] = res.files[index];\r
 +                      }\r
 +                      path = env_GetTempChildPath();\r
 +                      do\r
 +                      {\r
 +                              if (FAILED(piHandler->DeCompressArchive(hWnd, res.files[1].c_str(), path.c_str())))\r
 +                                      break;;\r
 +                              if (res.files[1].find(path) == 0)\r
 +                              {\r
 +                                      VERIFY(::DeleteFile(res.files[1].c_str()) || (LogErrorString(string_format(_T("DeleteFile(%s) failed"), res.files[1].c_str())), false));\r
 +                              }\r
 +                              BSTR pTmp = piHandler->GetDefaultName(hWnd, res.files[1].c_str());\r
 +                              res.files[1] = OLE2T(pTmp);\r
 +                              SysFreeString(pTmp);\r
 +                              res.files[1].insert(0, _T("\\"));\r
 +                              res.files[1].insert(0, path);\r
 +                      } while (piHandler = ArchiveGuessFormat(res.files[1].c_str()));\r
 +                      res.files[1] = path;\r
 +              }\r
 +              if (res.files.GetSize() > 2 && (piHandler = ArchiveGuessFormat(res.files[2].c_str())))\r
 +              {\r
 +                      if (!res.pTempPathContext)\r
 +                      {\r
 +                              res.pTempPathContext = new CTempPathContext;\r
 +                              for (int index = 0; index < res.files.GetSize(); index++)\r
 +                                      res.pTempPathContext->m_strDisplayRoot[index] = res.files[index];\r
 +                      }\r
 +                      path = env_GetTempChildPath();\r
 +                      do\r
 +                      {\r
 +                              if (FAILED(piHandler->DeCompressArchive(hWnd, res.files[2].c_str(), path.c_str())))\r
 +                                      break;;\r
 +                              if (res.files[2].find(path) == 0)\r
 +                              {\r
 +                                      VERIFY(::DeleteFile(res.files[2].c_str()) || (LogErrorString(string_format(_T("DeleteFile(%s) failed"), res.files[2].c_str())), false));\r
 +                              }\r
 +                              BSTR pTmp = piHandler->GetDefaultName(hWnd, res.files[1].c_str());\r
 +                              res.files[2] = OLE2T(pTmp);\r
 +                              SysFreeString(pTmp);\r
 +                              res.files[2].insert(0, _T("\\"));\r
 +                              res.files[2].insert(0, path);\r
 +                      } while (piHandler = ArchiveGuessFormat(res.files[2].c_str()));\r
 +                      res.files[2] = path;\r
 +              }\r
 +              if (res.files[1].empty())\r
 +              {\r
 +                      // assume Perry style patch\r
 +                      res.files[1] = path;\r
 +                      res.files[0] += _T("\\ORIGINAL");\r
 +                      res.files[1] += _T("\\ALTERED");\r
 +                      if (!PathFileExists(res.files[0].c_str()) || !PathFileExists(res.files[1].c_str()))\r
 +                      {\r
 +                              // not a Perry style patch: diff with itself...\r
 +                              res.files[0] = res.files[1] = path;\r
 +                      }\r
 +                      else\r
 +                      {\r
 +                              res.pTempPathContext->m_strDisplayRoot[0] += _T("\\ORIGINAL");\r
 +                              res.pTempPathContext->m_strDisplayRoot[1] += _T("\\ALTERED");\r
 +                      }\r
 +              }\r
 +      }\r
 +      catch (CException *e)\r
 +      {\r
 +              e->ReportError(MB_ICONSTOP);\r
 +              e->Delete();\r
 +      }\r
 +      return res;\r
 +}\r
 +\r
 +\r
Simple merge
diff --cc Src/AboutDlg.h
   * @brief Declaration file for CAboutDlg.
   *
   */
- // RCS ID line follows -- this is updated by CVS
- // $Id$
  #pragma once
  
 -#include "statlink.h"
 -#include "Picture.h"
 -#include "resource.h" // IDD_ABOUTBOX
 +#include <memory>
 +#include <Poco/BasicEvent.h>
 +#include "UnicodeString.h"
 +#include "MergeApp.h"
  
 -/** 
 - * @brief About-dialog class.
 - * 
 - * Shows About-dialog bitmap and draws version number and other
 - * texts into it.
 - */
 -class CAboutDlg : public CDialog
 +class CAboutDlg
  {
 +// Construction
  public:
        CAboutDlg();
 +      ~CAboutDlg();
 +      int DoModal();
  
 -// Dialog Data
 -      //{{AFX_DATA(CAboutDlg)
 -      enum { IDD = IDD_ABOUTBOX };
 -      CStatic m_ctlCompany;
 -      CStaticLink     m_ctlWWW;
 -      CString m_strVersion;
 -      CString m_strPrivateBuild;
 -      CPicture m_image;
 -      CFont m_font;
 -      //}}AFX_DATA
 +      AboutInfo m_info;
 +      Poco::BasicEvent<int> m_onclick_contributers;
  
 -      // ClassWizard generated virtual function overrides
 -      //{{AFX_VIRTUAL(CAboutDlg)
 -      protected:
 -      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 -      //}}AFX_VIRTUAL
 +private:
 +      CAboutDlg(const CAboutDlg &);
 +      CAboutDlg & operator=(const CAboutDlg &);
  
 -// Implementation
 -protected:
 -      //{{AFX_MSG(CAboutDlg)
 -      virtual BOOL OnInitDialog();
 -      //}}AFX_MSG
 -      DECLARE_MESSAGE_MAP()
 -public:
 -      afx_msg void OnBnClickedOpenContributors();
 -      afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
 -      afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
 +      class Impl;
 +      std::unique_ptr<Impl> m_pimpl;
  };
   *
   * @brief Implementation file for ClearCase dialog
   */
- // ID line follows -- this is updated by SVN
- // $Id$
  
  #include "stdafx.h"
- #include "CCPrompt.h"
+ #include "CCPromptDlg.h"
  #include "Merge.h"
 +#include "DDXHelper.h"
  
  #ifdef _DEBUG
  #define new DEBUG_NEW
  static char THIS_FILE[] = __FILE__;
  #endif
  
 -CCCPromptDlg::CCCPromptDlg(CWnd* pParent /*=NULL*/)
 -      : CDialog(CCCPromptDlg::IDD, pParent)
 -      , m_bMultiCheckouts(FALSE)
 -      , m_bCheckin(FALSE)
 +/**
 + * @brief A dialog for ClearCase checkout/checkin.
 + */
- class CCCPrompt::Impl : public CDialog
++class CCCPromptDlg::Impl : public CDialog
 +{
 +// Construction
 +public:
-       CCCPrompt::Impl(CCCPrompt *p, CWnd* pParent = NULL);   // standard constructor
++      CCCPromptDlg::Impl(CCCPromptDlg *p, CWnd* pParent = NULL);   // standard constructor
 +
 +// Dialog Data
-       //{{AFX_DATA(CCCPrompt::Impl)
++      //{{AFX_DATA(CCCPromptDlg::Impl)
 +      enum { IDD = IDD_CLEARCASE };
 +      //}}AFX_DATA
 +
 +
 +// Overrides
 +      // ClassWizard generated virtual function overrides
-       //{{AFX_VIRTUAL(CCCPrompt::Impl)
++      //{{AFX_VIRTUAL(CCCPromptDlg::Impl)
 +      protected:
 +      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 +      //}}AFX_VIRTUAL
 +
 +// Implementation
 +protected:
 +      virtual BOOL OnInitDialog();
 +
 +      // Generated message map functions
-       //{{AFX_MSG(CCCPrompt::Impl)
++      //{{AFX_MSG(CCCPromptDlg::Impl)
 +      afx_msg void OnSaveas();
 +      //}}AFX_MSG
 +      DECLARE_MESSAGE_MAP()
 +
 +private:
-       CCCPrompt *m_p;
++      CCCPromptDlg *m_p;
 +};
 +
- CCCPrompt::Impl::Impl(CCCPrompt *p, CWnd* pParent /*=NULL*/)
-       : CDialog(CCCPrompt::Impl::IDD, pParent)
++CCCPromptDlg::Impl::Impl(CCCPromptDlg *p, CWnd* pParent /*=NULL*/)
++      : CDialog(CCCPromptDlg::Impl::IDD, pParent)
 +      , m_p(p)
  {
  }
  
- void CCCPrompt::Impl::DoDataExchange(CDataExchange* pDX)
 -void CCCPromptDlg::DoDataExchange(CDataExchange* pDX)
++void CCCPromptDlg::Impl::DoDataExchange(CDataExchange* pDX)
  {
        CDialog::DoDataExchange(pDX);
-       //{{AFX_DATA_MAP(CCCPrompt::Impl)
 -      //{{AFX_DATA_MAP(CCCPromptDlg)
 -      DDX_Text(pDX, IDC_COMMENTS, m_comments);
 -      DDX_Check(pDX, IDC_MULTI_CHECKOUT, m_bMultiCheckouts);
 -      DDX_Check(pDX, IDC_CHECKIN, m_bCheckin);
++      //{{AFX_DATA_MAP(CCCPromptDlg::Impl)
 +      DDX_Text(pDX, IDC_COMMENTS, m_p->m_comments);
 +      DDX_Check(pDX, IDC_MULTI_CHECKOUT, m_p->m_bMultiCheckouts);
 +      DDX_Check(pDX, IDC_CHECKIN, m_p->m_bCheckin);
        //}}AFX_DATA_MAP
  }
  
- BEGIN_MESSAGE_MAP(CCCPrompt::Impl, CDialog)
-       //{{AFX_MSG_MAP(CCCPrompt::Impl)
 -BEGIN_MESSAGE_MAP(CCCPromptDlg, CDialog)
 -      //{{AFX_MSG_MAP(CCCPromptDlg)
++BEGIN_MESSAGE_MAP(CCCPromptDlg::Impl, CDialog)
++      //{{AFX_MSG_MAP(CCCPromptDlg::Impl)
        ON_BN_CLICKED(IDC_SAVE_AS, OnSaveas)
        //}}AFX_MSG_MAP
  END_MESSAGE_MAP()
@@@ -95,7 -57,7 +93,7 @@@
   * @brief Handler for WM_INITDIALOG; conventional location to initialize
   * controls. At this point dialog and control windows exist.
   */
- BOOL CCCPrompt::Impl::OnInitDialog() 
 -BOOL CCCPromptDlg::OnInitDialog() 
++BOOL CCCPromptDlg::Impl::OnInitDialog() 
  {
        theApp.TranslateDialog(m_hWnd);
        CDialog::OnInitDialog();
                      // EXCEPTION: OCX Property Pages should return FALSE
  }
  
- void CCCPrompt::Impl::OnSaveas() 
 -void CCCPromptDlg::OnSaveas() 
++void CCCPromptDlg::Impl::OnSaveas() 
  {
        EndDialog(IDC_SAVE_AS);
  }
- CCCPrompt::CCCPrompt()
-       : m_pimpl(new CCCPrompt::Impl(this))
 +
- CCCPrompt::~CCCPrompt() {}
- int CCCPrompt::DoModal() { return static_cast<int>(m_pimpl->DoModal()); }
++CCCPromptDlg::CCCPromptDlg()
++      : m_pimpl(new CCCPromptDlg::Impl(this))
 +      , m_bMultiCheckouts(false)
 +      , m_bCheckin(false)
 +{}
++CCCPromptDlg::~CCCPromptDlg() {}
++int CCCPromptDlg::DoModal() { return static_cast<int>(m_pimpl->DoModal()); }
 +
   * @brief Declaration file for ClearCase dialog.
   *
   */
- // ID line follows -- this is updated by SVN
- // $Id$
  #pragma once
  
 -/**
 - * @brief A dialog for ClearCase checkout/checkin.
 - */
 -class CCCPromptDlg : public CDialog
 +#include <memory>
 +#include "UnicodeString.h"
 +
- class CCCPrompt
++class CCCPromptDlg
  {
  // Construction
  public:
-       CCCPrompt();
-       ~CCCPrompt();
 -      CCCPromptDlg(CWnd* pParent = NULL);   // standard constructor
 -
 -// Dialog Data
 -      //{{AFX_DATA(CCCPromptDlg)
 -      enum { IDD = IDD_CLEARCASE };
 -      CString m_comments;
 -      //}}AFX_DATA
 -
++      CCCPromptDlg();
++      ~CCCPromptDlg();
 +      int DoModal();
  
 -// Overrides
 -      // ClassWizard generated virtual function overrides
 -      //{{AFX_VIRTUAL(CCCPromptDlg)
 -      protected:
 -      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 -      //}}AFX_VIRTUAL
 +      String  m_comments;
 +      bool m_bMultiCheckouts;
 +      bool m_bCheckin;
  
 -// Implementation
 -protected:
 -      virtual BOOL OnInitDialog();
 +private:
-       CCCPrompt(const CCCPrompt &);
-       CCCPrompt & operator=(const CCCPrompt &);
++      CCCPromptDlg(const CCCPromptDlg &);
++      CCCPromptDlg & operator=(const CCCPromptDlg &);
  
 -      // Generated message map functions
 -      //{{AFX_MSG(CCCPromptDlg)
 -      afx_msg void OnSaveas();
 -      //}}AFX_MSG
 -      DECLARE_MESSAGE_MAP()
 -
 -public:
 -      BOOL m_bMultiCheckouts;
 -      BOOL m_bCheckin;
 +      class Impl;
 +      std::unique_ptr<Impl> m_pimpl;
  };
 -
 -//{{AFX_INSERT_LOCATION}}
 -// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
Simple merge
  
  bool PutToClipboard(const String & text, HWND currentWindowHandle);
  bool GetFromClipboard(String & text, HWND currentWindowHandle);
- #endif // _CLIPBOARD_H_
 +
 +template<class Container>
 +void PutFilesToClipboard(const Container& list, HWND currentWindowHandle)
 +{
 +      String strPaths, strPathsSepSpc;
 +      strPaths.reserve(list.size() * MAX_PATH);
 +      strPathsSepSpc.reserve(list.size() * MAX_PATH);
 +
 +      for (Container::const_iterator it = list.begin(); it != list.end(); ++it)
 +      {
 +              String path = *it;
 +
 +              strPaths += path;
 +              strPaths += _T('\0');
 +
 +              strPathsSepSpc += _T("\"");
 +              strPathsSepSpc += path;
 +              strPathsSepSpc += _T("\" ");
 +      }
 +
 +      strPaths += _T('\0');
 +      strPathsSepSpc = string_trim_ws_end(strPathsSepSpc);
 +
 +      // CF_HDROP
 +      HGLOBAL hDrop = GlobalAlloc(GHND, sizeof(DROPFILES) + sizeof(TCHAR) * strPaths.length());
 +      if (!hDrop)
 +              return;
 +      TCHAR *pDrop = (TCHAR *)GlobalLock(hDrop);
 +      DROPFILES df = {0};
 +      df.pFiles = sizeof(DROPFILES);
 +      df.fWide = (sizeof(TCHAR) > 1);
 +      memcpy(pDrop, &df, sizeof(DROPFILES));
 +      memcpy((BYTE *)pDrop + sizeof(DROPFILES), (LPCTSTR)strPaths.c_str(), sizeof(TCHAR) * strPaths.length());
 +      GlobalUnlock(hDrop);
 +
 +      // CF_DROPEFFECT
 +      HGLOBAL hDropEffect = GlobalAlloc(GHND, sizeof(DWORD));
 +      if (!hDropEffect)
 +      {
 +              GlobalFree(hDrop);
 +              return;
 +      }
 +      *((DWORD *)(GlobalLock(hDropEffect))) = DROPEFFECT_COPY;
 +      GlobalUnlock(hDropEffect);
 +
 +      // CF_UNICODETEXT
 +      HGLOBAL hPathnames = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(TCHAR) * (strPathsSepSpc.length() + 1));
 +      if (!hPathnames)
 +      {
 +              GlobalFree(hDrop);
 +              GlobalFree(hDropEffect);
 +              return;
 +      }
 +      void *pPathnames = GlobalLock(hPathnames);
 +      memcpy((BYTE *)pPathnames, (LPCTSTR)strPathsSepSpc.c_str(), sizeof(TCHAR) * strPathsSepSpc.length());
 +      ((TCHAR *)pPathnames)[strPathsSepSpc.length()] = 0;
 +      GlobalUnlock(hPathnames);
 +
 +      UINT CF_DROPEFFECT = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
 +      if (::OpenClipboard(AfxGetMainWnd()->GetSafeHwnd()))
 +      {
 +              EmptyClipboard();
 +              SetClipboardData(CF_HDROP, hDrop);
 +              SetClipboardData(CF_DROPEFFECT, hDropEffect);
 +              SetClipboardData(GetClipTcharTextFormat(), hPathnames);
 +              CloseClipboard();
 +      }
 +}
Simple merge
@@@ -3,16 -3,12 +3,12 @@@
   *
   * @brief Declaration file for CLanguageSelect dialog.
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #if !defined(AFX_LANGUAGESELECT_H__4395A84F_E8DF_11D1_BBCB_00A024706EDC__INCLUDED_)
- #define AFX_LANGUAGESELECT_H__4395A84F_E8DF_11D1_BBCB_00A024706EDC__INCLUDED_
+ #pragma once
  
 -#include "CMoveConstraint.h"
 -
  #include <vector>
  #include <string>
 +#include <map>
 +#include "CMoveConstraint.h"
  
  /////////////////////////////////////////////////////////////////////////////
  // CLanguageSelect dialog
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -99,26 -89,3 +95,24 @@@ String string_join(const InputIterator
        }
        return result;
  }
- #endif // _UNICODE_STRING_
 +
 +template <class Formatter, class InputIterator>
 +String string_join(const InputIterator& begin, const InputIterator& end, const String& delim, Formatter func)
 +{
 +      String result;
 +      for (InputIterator it = begin; it != end; ++it)
 +      {
 +              if (!result.empty()) result.append(delim);
 +              result += func(*it);
 +      }
 +      return result;
 +}
 +
 +inline String string_to_str(int val) { return string_format(_T("%d"), val); }
 +inline String string_to_str(unsigned val) { return string_format(_T("%u"), val); }
 +inline String string_to_str(long val) { return string_format(_T("%ld"), val); }
 +inline String string_to_str(unsigned long val) { return string_format(_T("%lu"), val); }
 +inline String string_to_str(int64_t val) { return string_format(_T("%I64d"), val); }
 +inline String string_to_str(uint64_t val) { return string_format(_T("%I64u"), val); }
 +inline String string_to_str(float val) { return string_format(_T("%f"), val); }
 +inline String string_to_str(double val) { return string_format(_T("%f"), val); }
Simple merge
Simple merge
   *
   * @brief Declaration file for ConfirmFolderCopyDlg dialog
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #ifndef _CONFIRM_FOLDER_COPY_DLG_H_
- #define _CONFIRM_FOLDER_COPY_DLG_H_
+ #pragma once
  
  #include "CMoveConstraint.h"
 +#include "UnicodeString.h"
  
  /**
   * @brief Dialog for item copy confirmation.
diff --cc Src/Constants.h
Simple merge
diff --cc Src/DiffItem.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -45,12 -41,10 +41,10 @@@ public
  
        //{{AFX_DATA(DirCmpReportDlg)
        CSuperComboBox m_ctlReportFile; /**< Report filename control */
 -      CString m_sReportFile; /**< Report filename string */
 +      String m_sReportFile; /**< Report filename string */
        CComboBox m_ctlStyle; /**< Report type control */
        REPORT_TYPE m_nReportType; /**< Report type integer */
 -      BOOL m_bCopyToClipboard; /**< Do we copy report to clipboard? */
 -      BOOL m_bIncludeFileCmpReport; /**< Do we include file compare report in folder compare report? */
 +      bool m_bCopyToClipboard; /**< Do we copy report to clipboard? */
 +      bool m_bIncludeFileCmpReport; /**< Do we include file compare report in folder compare report? */
        //}}AFX_DATA
  };
- #endif // _DIRCMPREPORTDLG_H_
Simple merge
Simple merge
diff --cc Src/DirDoc.cpp
Simple merge
diff --cc Src/DirDoc.h
Simple merge
Simple merge
diff --cc Src/DirItem.cpp
Simple merge
Simple merge
diff --cc Src/DirView.cpp
Simple merge
diff --cc Src/DirView.h
Simple merge
@@@ -5,9 -5,11 +5,7 @@@
   *
   * @date  Created: 2003-08-19
   */
- // ID line follows -- this is updated by SVN
- // $Id: DirViewColItems.cpp 7063 2009-12-27 15:28:16Z kimmov $
 -
 -
 -#include "stdafx.h"
  #include "DirViewColItems.h"
 -#include <shlwapi.h>
  #include <cstdint>
  #include <Poco/Timestamp.h>
  #include "UnicodeString.h"
@@@ -5,18 -5,8 +5,14 @@@
   *
   * @date  Created: 2003-08-19
   */
- // RCS ID line follows -- this is updated by CVS
- // $Id: DirViewColItems.h 4619 2007-10-14 08:50:20Z jtuc $
- #ifndef DirViewColItems_h
- #define DirViewColItems_h
+ #pragma once
  
 +#include "UnicodeString.h"
 +#include <vector>
 +#include <sstream>
 +#include <cassert>
 +
 +struct DIFFITEM;
  class CDiffContext;
  
  // DirViewColItems typedefs
@@@ -49,83 -33,3 +45,81 @@@ struct DirColInf
  
  extern const int g_ncols;
  extern const int g_ncols3;
- #endif // DirViewColItems_h
 +
 +class DirViewColItems
 +{
 +public:
 +      DirViewColItems(int nDirs):
 +        m_nDirs(nDirs), m_numcols(-1), m_dispcols(-1) {}
 +      String GetColRegValueNameBase(int col) const;
 +      int GetColDefaultOrder(int col) const;
 +      const DirColInfo * GetDirColInfo(int col) const;
 +      bool IsColById(int col, const char *idname) const;
 +      bool IsColName(int col) const;
 +      bool IsColLmTime(int col) const;
 +      bool IsColMmTime(int col) const;
 +      bool IsColRmTime(int col) const;
 +      bool IsColStatus(int col) const;
 +      bool IsColStatusAbbr(int col) const;
 +      bool IsDefaultSortAscending(int col) const;
 +      String GetColDisplayName(int col) const;
 +      String GetColDescription(int col) const;
 +      int     GetColCount() const;
 +      int GetDispColCount() const { return m_dispcols; }
 +      String ColGetTextToDisplay(const CDiffContext *pCtxt, int col, const DIFFITEM & di) const;
 +      int ColSort(const CDiffContext *pCtxt, int col, const DIFFITEM & ldi, const DIFFITEM &rdi, bool bTreeMode) const;
 +
 +      int ColPhysToLog(int i) const { return m_invcolorder[i]; }
 +      int ColLogToPhys(int i) const { return m_colorder[i]; } /**< -1 if not displayed */
 +      void ClearColumnOrders();
 +      void MoveColumn(int psrc, int pdest);
 +      void ResetColumnOrdering();
 +      void SetColumnOrdering(const int colorder[]);
 +      void ValidateColumnOrdering();
 +      String ResetColumnWidths(int defcolwidth);
 +      void LoadColumnOrders(String colorders);
 +      String SaveColumnOrders();
 +
 +      /// Update all column widths (from registry to screen)
 +      // Necessary when user reorders columns
 +      template<class SetColumnWidthFunc>
 +      void LoadColumnWidths(String colwidths, SetColumnWidthFunc setcolwidth, int defcolwidth)
 +      {
 +              std::basic_istringstream<TCHAR> ss(colwidths);
 +              for (int i = 0; i < m_numcols; ++i)
 +              {
 +                      int phy = ColLogToPhys(i);
 +                      if (phy >= 0)
 +                      {
 +                              int w = defcolwidth;
 +                              ss >> w;
 +                              setcolwidth(phy, max(w, 10));
 +                      }
 +              }
 +      }
 +
 +      /** @brief store current column widths into registry */
 +      template<class GetColumnWidthFunc>
 +      String SaveColumnWidths(GetColumnWidthFunc getcolwidth)
 +      {
 +              String result;
 +              for (int i = 0; i < m_numcols; i++)
 +              {
 +                      int phy = ColLogToPhys(i);
 +                      if (phy >= 0)
 +                      {
 +                              if (!result.empty()) result += ' ';
 +                              result += string_to_str(getcolwidth(phy));
 +                      }
 +              }
 +              return result;
 +      }
 +
 +
 +private:
 +      int m_nDirs;
 +      int m_numcols;
 +      int m_dispcols;
 +      std::vector<int> m_colorder; /**< colorder[logical#]=physical# */
 +      std::vector<int> m_invcolorder; /**< invcolorder[physical]=logical# */
 +};
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc Src/IListCtrl.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc Src/MainFrm.cpp
Simple merge
diff --cc Src/MainFrm.h
Simple merge
diff --cc Src/Merge.cpp
Simple merge
diff --cc Src/Merge.h
Simple merge
Simple merge
      <ClCompile Include="ChildFrm.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DiffTextBuffer.cpp">\r
 +    <ClCompile Include="Common\CMoveConstraint.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
-     <ClCompile Include="ColorButton.cpp">\r
 -    <ClCompile Include="DiffViewBar.cpp">\r
++    <ClCompile Include="Common\ColorButton.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DirActions.cpp">\r
 +    <ClCompile Include="Common\CSubclass.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DirDoc.cpp">\r
 +    <ClCompile Include="DiffTextBuffer.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DirFrame.cpp">\r
 +    <ClCompile Include="DiffViewBar.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DirView.cpp">\r
 +    <ClCompile Include="DirDoc.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DirViewColHandler.cpp">\r
 +    <ClCompile Include="DirFrame.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
 -    <ClCompile Include="DirViewColItems.cpp">\r
 +    <ClCompile Include="DirView.cpp">\r
        <Filter>MFCGui\Source Files</Filter>\r
      </ClCompile>\r
      <ClCompile Include="EditorFilepathBar.cpp">\r
diff --cc Src/MergeApp.h
@@@ -27,25 -13,14 +26,23 @@@ void LogErrorString(const String& sz)
  void LogErrorStringUTF8(const std::string& sz);
  void AppErrorMessageBox(const String& msg);
  
 -      /** @brief Load string from string resources; shortcut for CString::LoadString */
 +namespace AppMsgBox
 +{
 +      enum
 +      {
 +              YES = 1,
 +              OK = 2,
 +              NO = 4,
 +              CANCEL = 8,
 +              YES_TO_ALL = 16,
 +              DONT_DISPLAY_AGAIN = 32,
 +      };
 +      int error(const String& msg, int type = OK);
 +      int warning(const String& msg, int type = OK);
 +      int information(const String& msg, int type = OK);
 +};
 +
 +/** @brief Load string from string resources; shortcut for CString::LoadString */
  String LoadResString(unsigned id);
  
- String tr(const std::string &str);
 -/** @brief Lang aware version of AfxFormatStrings() */
 -String LangFormatStrings(unsigned, const TCHAR * const *, int);
--
- #endif /* __MERGEAPP_H__ */
 -      /** @brief Lang aware version of AfxFormatString1() */
 -String LangFormatString1(unsigned, const TCHAR *);
 -
 -      /** @brief Lang aware version of AfxFormatString2() */
 -String LangFormatString2(unsigned, const TCHAR *, const TCHAR *);
++String tr(const std::string &str);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc Src/PatchDlg.h
Simple merge
Simple merge
diff --cc Src/PatchTool.h
@@@ -81,7 -77,5 +77,5 @@@ private
      std::vector<PATCHFILES> m_fileList; /**< List of files to patch. */
        CDiffWrapper m_diffWrapper; /**< DiffWrapper instance we use to create patch. */
        String m_sPatchFile; /**< Patch file path and filename. */
 -      BOOL m_bOpenToEditor; /**< Is patch file opened to external editor? */
 +      bool m_bOpenToEditor; /**< Is patch file opened to external editor? */
  };
- #endif        // _PATCHTOOL_H_
Simple merge
Simple merge
diff --cc Src/Plugins.cpp
Simple merge
Simple merge
@@@ -3,14 -3,8 +3,10 @@@
   *
   * @brief Declaration file for PluginsList dialog
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #ifndef _PLUGINS_LIST_DIALOG_H_
- #define _PLUGINS_LIST_DIALOG_H_
+ #pragma once
  
 +#include "UnicodeString.h"
 +
  /**
   * @brief A dialog listing plugins.
   * This dialog shows a list of currently available plugins. In addition
Simple merge
@@@ -3,14 -3,8 +3,10 @@@
   *
   * @brief Declaration file for ProjectFilePathsDlg dialog
   */
- // RCS ID line follows -- this is updated by CVS
- // $Id$
- #ifndef _PROJECTFILEPATHSDLG_H_
- #define _PROJECTFILEPATHSDLG_H_
+ #pragma once
  
 +#include "UnicodeString.h"
 +
  /**
   * @brief Dialog allowing user to load, edit and save project files.
   */
Simple merge
@@@ -40,8 -36,7 +36,7 @@@ protected
        DECLARE_MESSAGE_MAP()
  public:
        CStaticLink m_wwwLink;
 -      BOOL m_bEnableSupport;
 +      bool m_bEnableSupport;
        int m_nInstallType;
 -      BOOL m_bProbeType;
 +      bool m_bProbeType;
  };
- #endif // _PROP_ARCHIVE_H_
Simple merge
@@@ -4,14 -4,9 +4,10 @@@
   * @brief Declaration file for PropBackups propertyheet
   *
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #ifndef _PROPBACKUPS_H_
- #define _PROPBACKUPS_H_
+ #pragma once
  
  #include "OptionsPanel.h"
 +#include "UnicodeString.h"
  
  class COptionsMgr;
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -4,14 -4,9 +4,10 @@@
   * @brief Declaration file for PropEditor propertyheet
   *
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #if !defined(AFX_PROPEDITOR_H__1F2D57BB_6C09_488B_834D_575A94B2BDB8__INCLUDED_)
- #define AFX_PROPEDITOR_H__1F2D57BB_6C09_488B_834D_575A94B2BDB8__INCLUDED_
+ #pragma once
  
  #include "OptionsPanel.h"
 +#include "UnicodeString.h"
  
  class COptionsMgr;
  
Simple merge
Simple merge
Simple merge
   *
   * @brief Declaration file PropRegistry
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #ifndef PropRegistry_h_included
- #define PropRegistry_h_included
+ #pragma once
  
  #include "OptionsPanel.h"
 +#include "UnicodeString.h"
  
  class COptionsMgr;
  
Simple merge
diff --cc Src/PropShell.h
Simple merge
Simple merge
Simple merge
diff --cc Src/PropVss.cpp
Simple merge
diff --cc Src/PropVss.h
@@@ -3,14 -3,9 +3,10 @@@
   *
   * @brief Declaration of VSS properties dialog.
   */
- // ID line follows -- this is updated by SVN
- // $Id$
- #if !defined(AFX_PROPVSS_H__30AD07AF_E420_11D1_BBC5_00A024706EDC__INCLUDED_)
- #define AFX_PROPVSS_H__30AD07AF_E420_11D1_BBC5_00A024706EDC__INCLUDED_
+ #pragma once
  
  #include "OptionsPanel.h"
 +#include "UnicodeString.h"
  
  class COptionsMgr;
  
Simple merge
   *
   * @brief Declaration file for SaveClosingDlg dialog
   */
- // ID line follows -- this is updated by SVN
- // $Id: SaveClosingDlg.h 5444 2008-06-07 06:48:49Z kimmov $
- #ifndef _SAVECLOSINGDLG_H_
- #define _SAVECLOSINGDLG_H_
+ #pragma once
  
  #include "CMoveConstraint.h"
 +#include "UnicodeString.h"
  
  /////////////////////////////////////////////////////////////////////////////
  // SaveClosingDlg dialog
@@@ -81,9 -75,7 +76,7 @@@ protected
  // Implementation data
  private:
        prdlg::CMoveConstraint m_constraint; /**< Resizes dialog controls when dialog resized */
 -      BOOL m_bAskForLeft; /**< Is left file modified? */
 -      BOOL m_bAskForMiddle; /**< Is middle file modified? */
 -      BOOL m_bAskForRight; /**< Is right file modified? */
 +      bool m_bAskForLeft; /**< Is left file modified? */
 +      bool m_bAskForMiddle; /**< Is middle file modified? */
 +      bool m_bAskForRight; /**< Is right file modified? */
  };
- #endif // _SAVECLOSINGDLG_H_
Simple merge
Simple merge
Simple merge
@@@ -3,30 -3,24 +3,28 @@@
   *
   * @brief Implementation file for some source control-related functions.
   */
- // ID line follows -- this is updated by SVN
- // $Id$
  
 -#include "StdAfx.h"
 +#include <Windows.h>
 +#include "SourceControl.h"
  #define POCO_NO_UNWINDOWS 1
  #include <Poco/Process.h>
  #include <Poco/Format.h>
  #include <direct.h>
 +#include <Shlwapi.h>
 +#include <initguid.h>
 +#include "ssauto.h"
 +#include "MyCom.h"
  #include "UnicodeString.h"
  #include "unicoder.h"
 -#include "Merge.h"
 -#include "OptionsDef.h"
 +#include "MergeApp.h"
  #include "OptionsMgr.h"
 +#include "OptionsDef.h"
  #include "RegKey.h"
  #include "paths.h"
- #include "VssPrompt.h"
- #include "CCPrompt.h"
+ #include "VssPromptDlg.h"
 -#include "WaitStatusCursor.h"
 -#include "ssapi.h"      // BSP - Includes for Visual Source Safe COM interface
+ #include "CCPromptDlg.h"
 -#include "VSSHelper.h"
 +#include "WaitStatusCursor.h"
 +#include "coretools.h"
  
  using Poco::format;
  using Poco::Process;
@@@ -128,9 -74,9 +126,9 @@@ bool SourceControl::SaveToVersionContro
        case VCS_VSS4:  // Visual Source Safe
        {
                // Prompt for user choice
-               CVssPrompt dlg;
+               CVssPromptDlg dlg;
 -              dlg.m_strMessage = LangFormatString1(IDS_SAVE_FMT, strSavePath.c_str()).c_str();
 -              dlg.m_strProject = m_pVssHelper->GetProjectBase().c_str();
 +              dlg.m_strMessage = string_format_string1(_("Save changes to %1?"), strSavePath);
 +              dlg.m_strProject = m_vssHelper.GetProjectBase();
                dlg.m_strUser = m_strVssUser;          // BSP - Add VSS user name to dialog box
                dlg.m_strPassword = m_strVssPassword;
  
        case VCS_VSS5: // CVisual SourceSafe 5.0+ (COM)
        {
                // prompt for user choice
-               CVssPrompt dlg;
+               CVssPromptDlg dlg;
                CRegKeyEx reg;
 -              CString spath, sname;
  
 -              dlg.m_strMessage = LangFormatString1(IDS_SAVE_FMT, strSavePath.c_str()).c_str();
 -              dlg.m_strProject = m_pVssHelper->GetProjectBase().c_str();
 +              dlg.m_strMessage = string_format_string1(_("Save changes to %1?"), strSavePath);
 +              dlg.m_strProject = m_vssHelper.GetProjectBase();
                dlg.m_strUser = m_strVssUser;          // BSP - Add VSS user name to dialog box
                dlg.m_strPassword = m_strVssPassword;
                dlg.m_strSelectedDatabase = m_strVssDatabase;
        case VCS_CLEARCASE:
        {
                // prompt for user choice
-               CCCPrompt dlg;
+               CCCPromptDlg dlg;
                if (!m_CheckOutMulti)
                {
 -                      dlg.m_bMultiCheckouts = FALSE;
 +                      dlg.m_bMultiCheckouts = false;
                        dlg.m_comments = _T("");
 -                      dlg.m_bCheckin = FALSE;
 +                      dlg.m_bCheckin = false;
                        userChoice = dlg.DoModal();
                        m_CheckOutMulti = dlg.m_bMultiCheckouts;
                        m_strCCComment = dlg.m_comments;
diff --cc Src/StdAfx.cpp
Simple merge
diff --cc Src/StdAfx.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  //
  /////////////////////////////////////////////////////////////////////////////
  /** 
-  * @file  VssPrompt.cpp
+  * @file  VssPromptDlg.cpp
   *
-  * @brief Code for CVssPrompt::Impl class
 - * @brief Code for CVssPromptDlg class
++ * @brief Code for CVssPromptDlg::Impl class
   */
- // ID line follows -- this is updated by SVN
- // $Id$
  
  #include "stdafx.h"
- #include "VssPrompt.h"
+ #include "VssPromptDlg.h"
 +#include "SuperComboBox.h"
  #include "Merge.h"
  #include "RegKey.h"
 +#include "DDXHelper.h"
  
  #ifdef _DEBUG
  #define new DEBUG_NEW
  static char THIS_FILE[] = __FILE__;
  #endif
  
- class CVssPrompt::Impl : public CDialog
 +/**
 + * @brief Class for VSS dialog
 + */
-       CVssPrompt::Impl(CVssPrompt *p, CWnd* pParent = NULL);   // standard constructor
++class CVssPromptDlg::Impl : public CDialog
 +{
 +// Construction
 +public:
-       //{{AFX_DATA(CVssPrompt::Impl)
++      CVssPromptDlg::Impl(CVssPromptDlg *p, CWnd* pParent = NULL);   // standard constructor
 +
 +// Dialog Data
-       //{{AFX_VIRTUAL(CVssPrompt::Impl)
++      //{{AFX_DATA(CVssPromptDlg::Impl)
 +      enum { IDD = IDD_VSS };
 +      CSuperComboBox  m_ctlProject;
 +      //}}AFX_DATA
 +
 +
 +// Overrides
 +      // ClassWizard generated virtual function overrides
-       //{{AFX_MSG(CVssPrompt::Impl)
++      //{{AFX_VIRTUAL(CVssPromptDlg::Impl)
 +      protected:
 +      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 +      //}}AFX_VIRTUAL
 +
 +// Implementation
 +protected:
 +
 +      // Generated message map functions
-       CVssPrompt *m_p;
++      //{{AFX_MSG(CVssPromptDlg::Impl)
 +      virtual BOOL OnInitDialog();
 +      virtual void OnOK();
 +      afx_msg void OnSaveas();
 +      //}}AFX_MSG
 +      DECLARE_MESSAGE_MAP()
 +public:
 +      CComboBox m_ctlDBCombo;
 +      CButton m_ctlMultiCheckouts;
 +
 +private:
++      CVssPromptDlg *m_p;
 +};
 +
  /////////////////////////////////////////////////////////////////////////////
- // CVssPrompt::Impl dialog
 -// CVssPromptDlg dialog
++// CVssPromptDlg::Impl dialog
  
  
  /**
   * @brief Default constructor.
   * @param [in] pParent Pointer to parent component.
   */
- CVssPrompt::Impl::Impl(CVssPrompt *p, CWnd* pParent /*=NULL*/)
-       : CDialog(CVssPrompt::Impl::IDD, pParent)
 -CVssPromptDlg::CVssPromptDlg(CWnd* pParent /*=NULL*/)
 -      : CDialog(CVssPromptDlg::IDD, pParent)
 -      , m_strSelectedDatabase(_T(""))
 -      , m_bMultiCheckouts(FALSE)
 -      , m_bVCProjSync(FALSE)
++CVssPromptDlg::Impl::Impl(CVssPromptDlg *p, CWnd* pParent /*=NULL*/)
++      : CDialog(CVssPromptDlg::Impl::IDD, pParent)
 +      , m_p(p)
 +
  {
  }
  
  
- void CVssPrompt::Impl::DoDataExchange(CDataExchange* pDX)
 -void CVssPromptDlg::DoDataExchange(CDataExchange* pDX)
++void CVssPromptDlg::Impl::DoDataExchange(CDataExchange* pDX)
  {
        CDialog::DoDataExchange(pDX);
-       //{{AFX_DATA_MAP(CVssPrompt::Impl)
 -      //{{AFX_DATA_MAP(CVssPromptDlg)
++      //{{AFX_DATA_MAP(CVssPromptDlg::Impl)
        DDX_Control(pDX, IDC_PROJECT_COMBO, m_ctlProject);
 -      DDX_CBString(pDX, IDC_PROJECT_COMBO, m_strProject);
 -      DDX_Text(pDX, IDC_USER, m_strUser);
 -      DDX_Text(pDX, IDC_PASSWORD, m_strPassword);
 -      DDX_Text(pDX, IDC_MESSAGE, m_strMessage);
 +      DDX_CBString(pDX, IDC_PROJECT_COMBO, m_p->m_strProject);
 +      DDX_Text(pDX, IDC_USER, m_p->m_strUser);
 +      DDX_Text(pDX, IDC_PASSWORD, m_p->m_strPassword);
 +      DDX_Text(pDX, IDC_MESSAGE, m_p->m_strMessage);
        //}}AFX_DATA_MAP
 -      DDX_CBString(pDX, IDC_DATABASE_LIST, m_strSelectedDatabase);
 +      DDX_CBString(pDX, IDC_DATABASE_LIST, m_p->m_strSelectedDatabase);
        DDX_Control(pDX, IDC_DATABASE_LIST, m_ctlDBCombo);
 -      DDX_Check(pDX, IDC_MULTI_CHECKOUT, m_bMultiCheckouts);
 +      DDX_Check(pDX, IDC_MULTI_CHECKOUT, m_p->m_bMultiCheckouts);
        DDX_Control(pDX, IDC_MULTI_CHECKOUT, m_ctlMultiCheckouts);
 -      DDX_Check(pDX, IDC_VCPROJ_SYNC, m_bVCProjSync);
 +      DDX_Check(pDX, IDC_VCPROJ_SYNC, m_p->m_bVCProjSync);
  }
  
  
- BEGIN_MESSAGE_MAP(CVssPrompt::Impl, CDialog)
-       //{{AFX_MSG_MAP(CVssPrompt::Impl)
 -BEGIN_MESSAGE_MAP(CVssPromptDlg, CDialog)
 -      //{{AFX_MSG_MAP(CVssPromptDlg)
++BEGIN_MESSAGE_MAP(CVssPromptDlg::Impl, CDialog)
++      //{{AFX_MSG_MAP(CVssPromptDlg::Impl)
        ON_BN_CLICKED(IDC_SAVE_AS, OnSaveas)
        //}}AFX_MSG_MAP
  END_MESSAGE_MAP()
  
  /////////////////////////////////////////////////////////////////////////////
- // CVssPrompt::Impl message handlers
 -// CVssPromptDlg message handlers
++// CVssPromptDlg::Impl message handlers
  
  /**
   * @brief Initialize the dialog.
   * @return TRUE, unless focus is modified.
   */
- BOOL CVssPrompt::Impl::OnInitDialog()
 -BOOL CVssPromptDlg::OnInitDialog()
++BOOL CVssPromptDlg::Impl::OnInitDialog()
  {
        theApp.TranslateDialog(m_hWnd);
        CDialog::OnInitDialog();
  /**
   * @brief Close dialog with OK-button.
   */
- void CVssPrompt::Impl::OnOK()
 -void CVssPromptDlg::OnOK()
++void CVssPromptDlg::Impl::OnOK()
  {
        UpdateData(TRUE);
 -      if (m_strProject.IsEmpty())
 +      if (m_p->m_strProject.empty())
        {
                LangMessageBox(IDS_NOPROJECT,MB_ICONSTOP);
                m_ctlProject.SetFocus();
  /**
   * @brief Close dialog with Save As -button.
   */
- void CVssPrompt::Impl::OnSaveas()
 -void CVssPromptDlg::OnSaveas()
++void CVssPromptDlg::Impl::OnSaveas()
  {
        EndDialog(IDC_SAVE_AS);
  }
- CVssPrompt::CVssPrompt()
-       : m_pimpl(new CVssPrompt::Impl(this))
 +
 +
- CVssPrompt::~CVssPrompt() {}
- int CVssPrompt::DoModal() { return static_cast<int>(m_pimpl->DoModal()); }
++CVssPromptDlg::CVssPromptDlg()
++      : m_pimpl(new CVssPromptDlg::Impl(this))
 +      , m_strSelectedDatabase(_T(""))
 +      , m_bMultiCheckouts(false)
 +      , m_bVCProjSync(false)
 +{}
++CVssPromptDlg::~CVssPromptDlg() {}
++int CVssPromptDlg::DoModal() { return static_cast<int>(m_pimpl->DoModal()); }
  //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  /////////////////////////////////////////////////////////////////////////////
  /** 
-  * @file  VssPrompt.h
+  * @file  VssPromptDlg.h
   *
-  * @brief Declaration file for CVssPrompt
+  * @brief Declaration file for CVssPromptDlg
   */
- // RCS ID line follows -- this is updated by CVS
- // $Id$
  #pragma once
  
 -#include "SuperComboBox.h"
 -#include "afxwin.h"
 +#include <memory>
 +#include "UnicodeString.h"
  
- class CVssPrompt
 -/**
 - * @brief Class for VSS dialog
 - */
 -class CVssPromptDlg : public CDialog
++class CVssPromptDlg
  {
  // Construction
  public:
-       CVssPrompt();
-       ~CVssPrompt();
 -      CVssPromptDlg(CWnd* pParent = NULL);   // standard constructor
 -
 -// Dialog Data
 -      //{{AFX_DATA(CVssPromptDlg)
 -      enum { IDD = IDD_VSS };
 -      CSuperComboBox  m_ctlProject;
 -      CString m_strProject;
 -      CString m_strUser;
 -      CString m_strPassword;
 -      CString m_strMessage;
 -      //}}AFX_DATA
 -
 -
 -// Overrides
 -      // ClassWizard generated virtual function overrides
 -      //{{AFX_VIRTUAL(CVssPromptDlg)
 -      protected:
 -      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 -      //}}AFX_VIRTUAL
 -
 -// Implementation
 -protected:
 -
 -      // Generated message map functions
 -      //{{AFX_MSG(CVssPromptDlg)
 -      virtual BOOL OnInitDialog();
 -      virtual void OnOK();
 -      afx_msg void OnSaveas();
 -      //}}AFX_MSG
 -      DECLARE_MESSAGE_MAP()
 -public:
 -      CString m_strSelectedDatabase;
 -      CComboBox m_ctlDBCombo;
 -      BOOL m_bMultiCheckouts;
 -      CButton m_ctlMultiCheckouts;
 -      BOOL m_bVCProjSync;
++      CVssPromptDlg();
++      ~CVssPromptDlg();
 +      int DoModal();
 +
 +      String  m_strProject;
 +      String  m_strUser;
 +      String  m_strPassword;
 +      String  m_strMessage;
 +      String m_strSelectedDatabase;
 +      bool m_bMultiCheckouts;
 +      bool m_bVCProjSync;
 +
 +private:
-       CVssPrompt(const CVssPrompt &);
-       CVssPrompt & operator=(const CVssPrompt &);
++      CVssPromptDlg(const CVssPromptDlg &);
++      CVssPromptDlg & operator=(const CVssPromptDlg &);
 +
 +      class Impl;
 +      std::unique_ptr<Impl> m_pimpl;
  };
 -
 -//{{AFX_INSERT_LOCATION}}
 -// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
Simple merge
diff --cc Src/WMGotoDlg.h
   * @brief Declaration file for WMGotoDlg dialog.
   *
   */
- // ID line follows -- this is updated by SVN
- // $Id$
  #pragma once
  
 -/**
 - * @brief Class for Goto-dialog.
 - * This dialog allows user to go to certain line or or difference in the file
 - * compare. As there are two panels with different line numbers, there is a
 - * choice for target panel. When dialog is opened, its values are initialized
 - * for active file's line number.
 - */
 -class WMGotoDlg : public CDialog
 +#include <memory>
 +#include "UnicodeString.h"
 +
 +class WMGotoDlg
  {
  // Construction
  public:
Simple merge
@@@ -3,13 -3,88 +3,10 @@@
   *
   *  @brief Declaration WaitStatusCursor classes.
   */ 
- // ID line follows -- this is updated by SVN
- // $Id$
  #pragma once
  
 -class IStatusDisplay;
 -
 -/**
 - * @brief CustomStatusCursor enhanced cursor with GUI status feedback.
 - * 
 - * A CustomStatusCursor does what a CWaitCursor does, plus the caller selects
 - * the wait cursor and sets the status message. 
 - * Clients create WaitStatusCursors instead of CWaitCursors (don't mix them), and are isolated from
 - * status message implementation. Whoever wants to implement the status messages
 - * should call SetStatusDisplay to begin (or end) doing so.
 - *
 - * Example: CustomStatusCursor(0, IDC_APPSTARTING, _T("Rescanning"));
 - *
 - * @note This class must be called in the main thread
 - * It supports multithread (just uncomment the critical section code)
 - * But StatusDisplay does not... 
 - */
 -class CustomStatusCursor
 -{
 -// public interface
 -public:
 -      CustomStatusCursor(HINSTANCE hinst, LPCTSTR lpCursorName, LPCTSTR fmt, ...);
 -      CustomStatusCursor(HINSTANCE hinst, LPCTSTR lpCursorName, UINT fmtid, ...);
 -      void ChangeMsg(LPCTSTR fmt, ...);
 -      void End();
 -      ~CustomStatusCursor();
 -
 -// implementation data
 -protected:
 -      // default constructor for derivation, in two steps 'cause of variable argument list
 -      CustomStatusCursor();
 -      void Create(HINSTANCE hinst, LPCTSTR lpCursorName, LPCTSTR m_msg);
 -
 -private:
 -      INT_PTR posInStack;
 -      bool m_ended;
 -
 -      /**
 -       * @brief Number of active wait cursors + 1
 -       *
 -       * @note valid values : 0 (no wait cursor), 
 -       * >= 2 (stack[0] is the default cursor, and stack[1..n] are wait cursors)
 -       */
 -      static INT_PTR stackSize;
 -      /**
 -       * @brief Stack of messages, the currently displayed is the one on top of stack
 -       *
 -       * @note Allow overlapping creation/destruction of messages
 -       */
 -      static CStringArray msgStack;
 -      /**
 -       * @brief Stack of cursors, the currently displayed is the one on top of stack
 -       *
 -       * @note Allow overlapping creation/destruction of cursors
 -       */
 -      static CPtrArray cursorStack;
 -      static CDWordArray validStack;
 -
 -// critical section 
 -/*
 -private:
 -      static CRITICAL_SECTION CriticalSectionStack;
 -      static BOOL bCriticalSectionExist;
 -      static BOOL bCriticalSectionEntered;
 -      static void EnterStackCriticalSection();
 -      static void LeaveStackCriticalSection();
 -      static BOOL TryEnterStackCriticalSection();
 -*/
 -
 -// factor/class interface
 -public:
 -      static void SetStatusDisplay(IStatusDisplay * piStatusDisplay);
 -private:
 -      static IStatusDisplay * c_piStatusDisplay;
 -
 -      // for OnSetCursor
 -public:
 -      static BOOL HasWaitCursor();
 -      static void RestoreWaitCursor();
 -};
 +#include <memory>
 +#include "UnicodeString.h"
  
  /**
   * @brief WaitStatusCursor enhanced with GUI status feedback.
diff --cc Src/paths.cpp
Simple merge
diff --cc Src/paths.h
@@@ -44,7 -40,3 +40,5 @@@ void paths_SplitFilename(const String& 
  void paths_SplitViewName(const TCHAR *s, String * path, String * name, String * ext);
  String paths_GetPathOnly(const String& fullpath);
  bool paths_IsURLorCLSID(const String& path);
- #endif // paths_h_included
 +
 +inline String paths_AddTrailingSlash(const String& path) { return !paths_EndsWithSlash(path) ? path + _T("\\") : path; }