Skip to content

Clipboard Compare #1147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Docs/Manual/EN/Command_line.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@

<arg choice="opt" rep="norepeat"><option>/self-compare</option></arg>

<arg choice="opt" rep="norepeat"><option>/clipboard-compare</option></arg>

<arg><option>/minimize</option></arg>

<arg><option>/maximize</option></arg>
Expand Down Expand Up @@ -389,6 +391,13 @@
</listitem>
</varlistentry>

<varlistentry>
<term><option>/clipboard-compare</option></term>
<listitem>
<para>Compares the two most recent contents of the clipboard history.</para>
</listitem>
</varlistentry>

<varlistentry>
<indexterm>
<primary>WinMerge window</primary>
Expand Down
9 changes: 9 additions & 0 deletions Docs/Manual/JP/Command_line.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@

<arg choice="opt" rep="norepeat"><option>/self-compare</option></arg>

<arg choice="opt" rep="norepeat"><option>/clipboard-compare</option></arg>

<arg><option>/minimize</option></arg>

<arg><option>/maximize</option></arg>
Expand Down Expand Up @@ -388,6 +390,13 @@
</listitem>
</varlistentry>

<varlistentry>
<term><option>/clipboard-compare</option></term>
<listitem>
<para>クリップボード履歴の直近2つの内容を比較します。</para>
</listitem>
</varlistentry>

<varlistentry>
<indexterm>
<primary>WinMergeウインドウ</primary>
Expand Down
152 changes: 152 additions & 0 deletions Src/ClipboardHistory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* @file ClipboardHistory.cpp
*
* @brief Implementation for Clipboard history functions
*/

#include "StdAfx.h"
#include "ClipboardHistory.h"
#include "ClipBoard.h"
#include "Concurrent.h"
#include "UniFile.h"

#ifdef _WIN64

#include <winrt/windows.foundation.collections.h>
#include <winrt/windows.applicationmodel.datatransfer.h>
#include <winrt/windows.graphics.imaging.h>
#include <winrt/windows.storage.streams.h>

using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Graphics::Imaging;
using namespace winrt::Windows::Storage;

#endif

namespace ClipboardHistory
{
namespace impl
{
std::shared_ptr<TempFile> CreateTempTextFile(const String& text)
{
std::shared_ptr<TempFile> pTempFile(new TempFile());
pTempFile->Create(_T("CLP"), L".txt");
String path = pTempFile->GetPath();
UniStdioFile file;
if (file.OpenCreateUtf8(path))
{
file.WriteString(text);
file.Close();
}
return pTempFile;
}

String GetClipboardText()
{
String text;
GetFromClipboard(text, nullptr);
return text;
}

#ifdef _WIN64
std::shared_ptr<TempFile> CreateTempBitmapFile(const DataPackageView& dataPackageView)
{
std::shared_ptr<TempFile> pTempFile(new TempFile());
pTempFile->Create(_T("CLP"), _T(".png"));

auto streamReference = dataPackageView.GetBitmapAsync().get();
auto inputStream = streamReference.OpenReadAsync().get();
auto decoder = BitmapDecoder::CreateAsync(inputStream).get();
auto bitmap = decoder.GetSoftwareBitmapAsync().get();

auto outputFile = StorageFile::GetFileFromPathAsync(pTempFile->GetPath()).get();
auto outputStream = outputFile.OpenAsync(FileAccessMode::ReadWrite).get();
auto encoder = BitmapEncoder::CreateAsync(BitmapEncoder::PngEncoderId(), outputStream).get();
encoder.SetSoftwareBitmap(bitmap);
encoder.FlushAsync().get();

return pTempFile;
}
#endif

std::vector<Item> GetItems(unsigned num)
{
std::vector<Item> result;
#ifdef _WIN64
try
{
auto historyItems = Clipboard::GetHistoryItemsAsync().get();
auto items = historyItems.Items();
for (unsigned int i = 0; i < num; ++i)
{
result.emplace_back();
auto& item = result.back();
if (i < items.Size())
{
try
{
auto dataPackageView = items.GetAt(i).Content();
item.timestamp = winrt::clock::to_time_t(items.GetAt(i).Timestamp());
if (dataPackageView.Contains(StandardDataFormats::Text()))
{
item.pTextTempFile = CreateTempTextFile(dataPackageView.GetTextAsync().get().c_str());
}
if (dataPackageView.Contains(StandardDataFormats::Bitmap()))
{
item.pBitmapTempFile = CreateTempBitmapFile(dataPackageView);
}
if (!item.pTextTempFile && !item.pBitmapTempFile)
{
item.pTextTempFile = CreateTempTextFile(_T(""));
}
}
catch (const winrt::hresult_error& e)
{
item.pTextTempFile = CreateTempTextFile(e.message().c_str());
}
}
else
{
if (i == 0)
time(&item.timestamp);
item.pTextTempFile = CreateTempTextFile(i == 0 ?
GetClipboardText() :
(!Clipboard::IsHistoryEnabled() ? _("Clipboard history is disabled.\r\nTo enable clipboard history, press Windows logo key + V and then click the Turn on button.") : _T("")));
}
}
}
catch (const winrt::hresult_error&)
{
for (unsigned int i = 0; i < num; ++i)
{
result.emplace_back();
auto& item = result.back();
if (i == 0)
time(&item.timestamp);
item.pTextTempFile = CreateTempTextFile(
i == 0 ? GetClipboardText() : _("This system does not support clipboard history."));
}
}
#else
for (unsigned int i = 0; i < num; ++i)
{
result.emplace_back();
auto& item = result.back();
if (i == 0)
time(&item.timestamp);
item.pTextTempFile = CreateTempTextFile(
i == 0 ? GetClipboardText() : _("The 32-bit version of WinMerge does not support Clipboard Compare"));
}
#endif
return result;
}
}

std::vector<Item> GetItems(unsigned num)
{
auto task = Concurrent::CreateTask([num] {
return impl::GetItems(num);
});
return task.Get();
}
}
23 changes: 23 additions & 0 deletions Src/ClipboardHistory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @file ClipboardHistory.h
*
* @brief Declaration file for Clipboard history functions
*/
#pragma once

#include "UnicodeString.h"
#include "TempFile.h"
#include <memory>
#include <vector>
#include <ctime>

namespace ClipboardHistory
{
struct Item
{
time_t timestamp;
std::shared_ptr<TempFile> pTextTempFile;
std::shared_ptr<TempFile> pBitmapTempFile;
};
std::vector<Item> GetItems(unsigned num);
}
51 changes: 51 additions & 0 deletions Src/MainFrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
#include "TFile.h"
#include "Shell.h"
#include "WindowsManagerDialog.h"
#include "ClipboardHistory.h"
#include "locality.h"

using std::vector;
using boost::begin;
Expand Down Expand Up @@ -223,6 +225,8 @@ BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
ON_COMMAND(ID_FILE_OPENPROJECT, OnFileOpenProject)
ON_COMMAND(ID_FILE_SAVEPROJECT, OnSaveProject)
ON_COMMAND(ID_FILE_OPENCONFLICT, OnFileOpenConflict)
ON_COMMAND(ID_FILE_OPENCLIPBOARD, OnFileOpenClipboard)
ON_COMMAND(ID_EDIT_PASTE, OnFileOpenClipboard)
ON_COMMAND_RANGE(ID_MRU_FIRST, ID_MRU_LAST, OnMRUs)
ON_UPDATE_COMMAND_UI(ID_MRU_FIRST, OnUpdateNoMRUs)
ON_UPDATE_COMMAND_UI(ID_NO_MRU, OnUpdateNoMRUs)
Expand Down Expand Up @@ -2536,6 +2540,53 @@ void CMainFrame::OnFileOpenConflict()
}
}

/**
* @brief Called when user selects File/Open Clipboard
*/
void CMainFrame::OnFileOpenClipboard()
{
DoOpenClipboard();
}

bool CMainFrame::DoOpenClipboard(UINT nID, int nBuffers /*= 2*/, const DWORD dwFlags[] /*= nullptr*/,
const String strDesc[] /*= nullptr*/, const PackingInfo* infoUnpacker /*= nullptr*/,
const PrediffingInfo* infoPrediffer /*= nullptr*/, const OpenFileParams* pOpenParams /*= nullptr*/)
{
auto historyItems = ClipboardHistory::GetItems(nBuffers);

String strDesc2[3];
DWORD dwFlags2[3];
for (int i = 0; i < nBuffers; ++i)
{
int64_t t = historyItems[nBuffers - i - 1].timestamp;
String timestr = t == 0 ? _T("---") : locality::TimeString(&t);
strDesc2[i] = (strDesc && !strDesc[i].empty()) ?
strDesc[i] : strutils::format(_("Clipboard at %s"), timestr);
dwFlags2[i] = (dwFlags ? dwFlags[i] : 0) | FFILEOPEN_NOMRU;
}
for (int i = 0; i < 2; ++i)
{
PathContext tmpPathContext;
for (int pane = 0; pane < nBuffers; ++pane)
{
auto item = historyItems[nBuffers - pane - 1];
if (i == 0 && item.pBitmapTempFile)
{
tmpPathContext.SetPath(pane, item.pBitmapTempFile->GetPath());
m_tempFiles.push_back(item.pBitmapTempFile);
}
if (i == 1 && item.pTextTempFile)
{
tmpPathContext.SetPath(pane, item.pTextTempFile->GetPath());
m_tempFiles.push_back(item.pTextTempFile);
}
}
if (tmpPathContext.GetSize() == nBuffers)
DoFileOpen(nID, &tmpPathContext, dwFlags2, strDesc2, _T(""), infoUnpacker, infoPrediffer, pOpenParams);
}
return true;
}

/**
* @brief Select and open conflict file for resolving.
* This function lets user to select conflict file to resolve.
Expand Down
4 changes: 4 additions & 0 deletions Src/MainFrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ class CMainFrame : public CMDIFrameWnd
const PrediffingInfo * infoPrediffer = nullptr,
const OpenFileParams *pOpenParams = nullptr);
bool DoOpenConflict(const String& conflictFile, const String strDesc[] = nullptr, bool checked = false);
bool DoOpenClipboard(UINT nID = 0, int nBuffers = 2, const DWORD dwFlags[] = nullptr, const String strDesc[] = nullptr,
const PackingInfo* infoUnpacker = nullptr, const PrediffingInfo * infoPrediffer = nullptr,
const OpenFileParams* pOpenParams = nullptr);
bool DoSelfCompare(UINT nID, const String& file, const String strDesc[] = nullptr,
const PackingInfo* infoUnpacker = nullptr, const PrediffingInfo * infoPrediffer = nullptr,
const OpenFileParams* pOpenParams = nullptr);
Expand Down Expand Up @@ -332,6 +335,7 @@ class CMainFrame : public CMDIFrameWnd
afx_msg void OnHelpReleasenotes();
afx_msg void OnHelpTranslations();
afx_msg void OnFileOpenConflict();
afx_msg void OnFileOpenClipboard();
afx_msg void OnPluginsList();
afx_msg void OnUpdatePluginName(CCmdUI* pCmdUI);
afx_msg void OnUpdateStatusNum(CCmdUI* pCmdUI);
Expand Down
15 changes: 10 additions & 5 deletions Src/Merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,15 +795,20 @@ bool CMergeApp::ParseArgsAndDoOpen(MergeCmdLineInfo& cmdInfo, CMainFrame* pMainF
}
else if (cmdInfo.m_Files.GetSize() == 0) // if there are no input args, we can check the display file dialog flag
{
if (!cmdInfo.m_bNewCompare)
if (cmdInfo.m_bNewCompare)
{
bool showFiles = m_pOptions->GetBool(OPT_SHOW_SELECT_FILES_AT_STARTUP);
if (showFiles)
pMainFrame->DoFileOrFolderOpen();
bCompared = pMainFrame->DoFileNew(nID, 2, strDesc, infoPrediffer.get(), pOpenParams.get());
}
else if (cmdInfo.m_bClipboardCompare)
{
DWORD dwFlags[3] = {cmdInfo.m_dwLeftFlags, cmdInfo.m_dwRightFlags, FFILEOPEN_NONE};
bCompared = pMainFrame->DoOpenClipboard(nID, 2, dwFlags, strDesc, infoUnpacker.get(), infoPrediffer.get(), pOpenParams.get());
}
else
{
bCompared = pMainFrame->DoFileNew(nID, 2, strDesc, infoPrediffer.get(), pOpenParams.get());
bool showFiles = m_pOptions->GetBool(OPT_SHOW_SELECT_FILES_AT_STARTUP);
if (showFiles)
pMainFrame->DoFileOrFolderOpen();
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions Src/Merge.rc
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ BEGIN
END
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM "Open Conflic&t File...", ID_FILE_OPENCONFLICT
MENUITEM "Open C&lipboard", ID_FILE_OPENCLIPBOARD
MENUITEM SEPARATOR
MENUITEM "Open Pro&ject...\tCtrl+J", ID_FILE_OPENPROJECT
MENUITEM "Sa&ve Project...", ID_FILE_SAVEPROJECT
Expand All @@ -244,6 +245,8 @@ BEGIN
END
POPUP "&Edit"
BEGIN
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
MENUITEM SEPARATOR
MENUITEM "&Options...", ID_OPTIONS
END
POPUP "&View"
Expand Down Expand Up @@ -319,6 +322,7 @@ BEGIN
END
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM "Open Conflic&t File...", ID_FILE_OPENCONFLICT
MENUITEM "Open C&lipboard", ID_FILE_OPENCLIPBOARD
MENUITEM SEPARATOR
MENUITEM "Open Pro&ject...\tCtrl+J", ID_FILE_OPENPROJECT
MENUITEM "Sa&ve Project...", ID_FILE_SAVEPROJECT
Expand Down Expand Up @@ -477,6 +481,7 @@ BEGIN
END
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM "Open Conflic&t File...", ID_FILE_OPENCONFLICT
MENUITEM "Open C&lipboard", ID_FILE_OPENCLIPBOARD
MENUITEM SEPARATOR
MENUITEM "Open Pro&ject...\tCtrl+J", ID_FILE_OPENPROJECT
MENUITEM "Sa&ve Project...", ID_FILE_SAVEPROJECT
Expand Down Expand Up @@ -4011,6 +4016,14 @@ BEGIN
IDS_FILTER_APPLIED "Filter applied"
END

STRINGTABLE
BEGIN
IDS_CLIPBOARDHISTORY_TIME "Clipboard at %s"
IDS_CLIPBOARDHISTORY_DISABLED "Clipboard history is disabled.\r\nTo enable clipboard history, press Windows logo key + V and then click the Turn on button."
IDS_CLIPBOARDHISTORY_NOT_SUPPORTED1 "This system does not support clipboard history."
IDS_CLIPBOARDHISTORY_NOT_SUPPORTED2 "The 32-bit version of WinMerge does not support Clipboard Compare"
END

#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////

Expand Down
Loading