Explorar el Código

Merge pull request #814 from sabrogden/edit-images

support editing images through external editors
sabrogden hace 9 meses
padre
commit
6c46cf935e
Se han modificado 10 ficheros con 220 adiciones y 28 borrados
  1. 30 1
      src/AdvGeneral.cpp
  2. 22 2
      src/CP_Main.cpp
  3. 12 2
      src/Clip.cpp
  4. 1 1
      src/Clip.h
  5. 91 14
      src/ClipEditThread.cpp
  6. 2 0
      src/ClipEditThread.h
  7. 36 0
      src/Options.cpp
  8. 11 0
      src/Options.h
  9. 14 7
      src/QPasteWnd.cpp
  10. 1 1
      src/QPasteWnd.h

+ 30 - 1
src/AdvGeneral.cpp

@@ -152,6 +152,9 @@ END_MESSAGE_MAP()
 #define SETTING_QR_CODE_URL 101
 #define SETTING_APPEND_NAME_IP 102
 #define SETTING_USE_UTF8_FOR_DIFF 103
+#define SETTING_IMAGE_EDITOR_PATH 104
+#define SETTING_CLIP_EDIT_SAVE_DELAY_AFTER_LOAD 105
+#define SETTING_ClIP_EDIT_SAVE_DELAY_AFTER_SAVE 106
 
 BOOL CAdvGeneral::OnInitDialog()
 {
@@ -194,6 +197,10 @@ BOOL CAdvGeneral::OnInitDialog()
 	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Amount of text to save for description"), CGetSetOptions::m_bDescTextSize, _T(""), SETTING_DESC_SIZE));
 	AddTrueFalse(pGroupTest, _T("Center window below cursor or caret"), CGetSetOptions::GetCenterWindowBelowCursorOrCaret(), SETTING_CENTER_WINDOW_BELOW_CURSOR_CARET);
 	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Copy and save clipboard delay (ms)"), (long)CGetSetOptions::GetCopyAndSveDelay(), _T(""), SETTING_COPY_SAVE_DELAY));
+
+	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Clip edit save delay after load"), (long)(CGetSetOptions::GetClipEditSaveDelayAfterLoadSeconds()), _T(""), SETTING_CLIP_EDIT_SAVE_DELAY_AFTER_LOAD));
+	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Clip edit save delay after Save"), (long)(CGetSetOptions::GetClipEditSaveDelayAfterSaveSeconds()), _T(""), SETTING_ClIP_EDIT_SAVE_DELAY_AFTER_SAVE));
+
 	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Clipboard restore delay after copy buffer sent paste (ms, default: 750)"), (long)(CGetSetOptions::GetDittoRestoreClipboardDelay()), _T(""), SETTING_CLIPBOARD_RESTORE_AFTER_COPY_BUFFER_DELAY));
 
 	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Default paste string"), CGetSetOptions::GetDefaultPasteString(), _T(""), SETTING_DEFAULT_PASTE_STRING));
@@ -232,6 +239,10 @@ BOOL CAdvGeneral::OnInitDialog()
 	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Ignore copies faster than (ms) (default: 500)"), (long)CGetSetOptions::GetSaveClipDelay(), _T(""), SETTING_IGNORE_FALSE_COPIES_DELAY));
 	pGroupTest->AddSubItem(new CMFCPropertyGridProperty(_T("Ignore annoying CF_DIB when a clip is detected as text content"), CGetSetOptions::GetIgnoreAnnoyingCFDIB(), _T("Case insensitive. Recommended option is \"excel.exe; onenote.exe; powerpnt.exe\" "), SETTING_IGNORE_ANNOYING_CF_DIB));
 
+	static TCHAR BASED_CODE szImageEditorFilter[] = _T("Applications(*.exe)|*.exe||");
+	CMFCPropertyGridFileProperty* pImageEditorProp = new CMFCPropertyGridFileProperty(_T("Image editor path (empty for system mapping)"), TRUE, CGetSetOptions::GetImageEditorPath(), _T("exe"), 0, szImageEditorFilter, (LPCTSTR)0, SETTING_IMAGE_EDITOR_PATH);
+	pGroupTest->AddSubItem(pImageEditorProp);
+
 	pGroupTest->AddSubItem( new CMFCPropertyGridProperty(_T("Maximum clip size in bytes (0 for no limit)"), CGetSetOptions::m_lMaxClipSizeInBytes, _T(""), SETTING_MAX_CLIP_SIZE));
 		
 	AddTrueFalse(pGroupTest, _T("Maintain search view"), CGetSetOptions::GetMaintainSearchView(), SETTING_MAINTAIN_SEARCH_VIEW);
@@ -254,7 +265,7 @@ BOOL CAdvGeneral::OnInitDialog()
 	pGroupTest->AddSubItem(pFileProp);
 
 	static TCHAR BASED_CODE szTextEditorFilter[] = _T("Applications(*.exe)|*.exe||");
-	CMFCPropertyGridFileProperty* pTextEditorProp = new CMFCPropertyGridFileProperty(_T("Text editor path"), TRUE, CGetSetOptions::GetTextEditorPath(), _T("exe"), 0, szTextEditorFilter, (LPCTSTR)0, SETTING_TEXT_EDITOR_PATH);
+	CMFCPropertyGridFileProperty* pTextEditorProp = new CMFCPropertyGridFileProperty(_T("Text editor path (empty for system mapping)"), TRUE, CGetSetOptions::GetTextEditorPath(), _T("exe"), 0, szTextEditorFilter, (LPCTSTR)0, SETTING_TEXT_EDITOR_PATH);
 	pGroupTest->AddSubItem(pTextEditorProp);
 
 	AddTrueFalse(pGroupTest, _T("Paste clip in active window after selection"), CGetSetOptions::GetSendPasteAfterSelection(), SETTING_PASTE_IN_ACTIVE_WINDOW);
@@ -885,6 +896,12 @@ void CAdvGeneral::OnBnClickedOk()
 					CGetSetOptions::SetTextEditorPath(pNewValue->bstrVal);
 				}
 				break;
+			case SETTING_IMAGE_EDITOR_PATH:
+				if (wcscmp(pNewValue->bstrVal, pOrigValue->bstrVal) != 0)
+				{
+					CGetSetOptions::SetImageEditorPath(pNewValue->bstrVal);
+				}
+				break;
 			case SETTING_RTF_EDITOR_PATH:
 				if (wcscmp(pNewValue->bstrVal, pOrigValue->bstrVal) != 0)
 				{
@@ -918,6 +935,18 @@ void CAdvGeneral::OnBnClickedOk()
 					CGetSetOptions::SetPreferUtf8ForCompare(val);
 				}
 				break;
+			case SETTING_CLIP_EDIT_SAVE_DELAY_AFTER_LOAD:
+				if (pNewValue->lVal != pOrigValue->lVal)
+				{
+					CGetSetOptions::SetClipEditSaveDelayAfterLoadSeconds(pNewValue->lVal);
+				}
+				break;
+			case SETTING_ClIP_EDIT_SAVE_DELAY_AFTER_SAVE:
+				if (pNewValue->lVal != pOrigValue->lVal)
+				{
+					CGetSetOptions::SetClipEditSaveDelayAfterSaveSeconds(pNewValue->lVal);
+				}
+				break;
 			}
 		}
 	}

+ 22 - 2
src/CP_Main.cpp

@@ -1105,7 +1105,7 @@ bool CCP_MainApp::EditItems(CClipIDs &Ids, bool bShowError, bool forceTextEdit)
 		const int id = Ids[i];		
 
 		CClip clip;
-		if (id >= 0 && clip.LoadFormats(id, true, true) == false)
+		if (id >= 0 && clip.LoadFormats(id) == false)
 		{
 			Log(StrF(_T("Failed to load formats for clipId: %d"), id));
 			continue;
@@ -1114,6 +1114,7 @@ bool CCP_MainApp::EditItems(CClipIDs &Ids, bool bShowError, bool forceTextEdit)
 		bool unicodeFile = false;
 		bool asciFile = false;
 		bool rtfFile = false;
+		bool imageFile = false;
 		CString exePath;
 		CString extension;
 		if (forceTextEdit == false && clip.ContainsClipFormat(theApp.m_RTFFormat))
@@ -1140,6 +1141,18 @@ bool CCP_MainApp::EditItems(CClipIDs &Ids, bool bShowError, bool forceTextEdit)
 			unicodeFile = true;
 			exePath = CGetSetOptions::GetTextEditorPath();
 		}
+		else if (clip.ContainsClipFormat(theApp.m_PNG_Format))
+		{
+			imageFile = true;
+			extension = _T("png");
+			exePath = CGetSetOptions::GetImageEditorPath();
+		}
+		else if (clip.ContainsClipFormat(CF_DIB))
+		{
+			imageFile = true;
+			extension = _T("bmp");
+			exePath = CGetSetOptions::GetImageEditorPath();
+		}		
 		else
 		{
 			continue;
@@ -1175,7 +1188,14 @@ bool CCP_MainApp::EditItems(CClipIDs &Ids, bool bShowError, bool forceTextEdit)
 
 		m_editThread.WatchFile(savePath);
 
-		clip.WriteTextToFile(savePath, unicodeFile, asciFile, rtfFile, (id == -1));
+		if (imageFile)
+		{
+			clip.WriteImageToFile(savePath);
+		}
+		else
+		{
+			clip.WriteTextToFile(savePath, unicodeFile, asciFile, rtfFile, (id == -1));
+		}		
 
 		SHELLEXECUTEINFO sei = { sizeof(sei) };
 		sei.fMask = SEE_MASK_NOCLOSEPROCESS;

+ 12 - 2
src/Clip.cpp

@@ -160,7 +160,7 @@ void CClipFormat::Free()
 
 Gdiplus::Bitmap *CClipFormat::CreateGdiplusBitmap()
 {
-	if (this->m_cfType != CF_DIB && this->m_cfType == theApp.m_PNG_Format)
+	if (this->m_cfType != CF_DIB && this->m_cfType != theApp.m_PNG_Format)
 		return NULL;
 
 	Gdiplus::Bitmap *gdipBitmap;
@@ -1812,7 +1812,7 @@ BOOL CClip::WriteTextToHtmlFile(CString path)
 	return ret;
 }
 
-BOOL CClip::SaveFormats(CString *unicode, CStringA *asci, CStringA *rtf, BOOL updateDescription)
+BOOL CClip::SaveFormats(CString *unicode, CStringA *asci, CStringA *rtf, BOOL updateDescription, std::vector<BYTE> *cf_dibBytes, std::vector<BYTE>* pngBytes)
 {
 	ARRAY deletedData;
 	for (INT_PTR i = m_Formats.GetSize() - 1; i >= 0; i--)
@@ -1822,6 +1822,16 @@ BOOL CClip::SaveFormats(CString *unicode, CStringA *asci, CStringA *rtf, BOOL up
 
 	EmptyFormats();
 
+	if (cf_dibBytes != nullptr && cf_dibBytes->size() > 0)
+	{
+		AddFormat(CF_DIB, cf_dibBytes->data(), cf_dibBytes->size(), false);
+	}
+
+	if (pngBytes != nullptr && pngBytes->size() > 0)
+	{
+		AddFormat(theApp.m_PNG_Format, pngBytes->data(), pngBytes->size(), false);
+	}
+
 	if (rtf != nullptr)
 	{
 		const int nLength = rtf->GetLength() + sizeof(char);

+ 1 - 1
src/Clip.h

@@ -197,7 +197,7 @@ public:
 	BOOL WriteImageToFile(CString path);
 	BOOL WriteTextToHtmlFile(CString path);
 
-	BOOL SaveFormats(CString* unicode, CStringA* asci, CStringA* rtf, BOOL updateDescription);
+	BOOL SaveFormats(CString* unicode, CStringA* asci, CStringA* rtf, BOOL updateDescription, std::vector<BYTE>* cf_dibBytes = nullptr, std::vector<BYTE>* pngBytes = nullptr);
 
 	// Allocates a Global containing the requested Clip's Format Data
 	static HGLOBAL LoadFormat(int id, UINT cfType);

+ 91 - 14
src/ClipEditThread.cpp

@@ -163,9 +163,9 @@ void CClipEditThread::OnFileChanged()
 				{
 					auto startEdit = m_fileEditStarts[fileName];
 					auto diff = CTime::GetCurrentTime() - startEdit;
-					if (diff.GetTotalSeconds() < 2)
+					if (diff.GetTotalSeconds() < CGetSetOptions::m_clipEditSaveDelayAfterLoadSeconds)
 					{
-						Log(StrF(_T("%s has changed close to when we started editing the file, diff: %d, not handling change"), fileName, diff.GetTotalSeconds()));
+						Log(StrF(_T("%s has changed close to when we started editing the file, diff: %lld, limit: %d, not handling change"), fileName, diff.GetTotalSeconds(), CGetSetOptions::m_clipEditSaveDelayAfterLoadSeconds));
 						addToChanges = false;
 					}
 				}
@@ -212,7 +212,7 @@ void CClipEditThread::OnFileChanged()
 
 	if (fileModified)
 	{
-		m_waitTimeout = 2000;
+		m_waitTimeout = CGetSetOptions::m_clipEditSaveDelayAfterSaveSeconds * 1000;
 	}
 }
 
@@ -246,30 +246,46 @@ bool CClipEditThread::SaveToClip(CString filePath, int id)
 	CString unicodeText;
 	CStringA utf8Text;
 	bool unicode = false;
+	std::vector<BYTE> cf_dibBytes;
+	std::vector<BYTE> pngBytes;
 	
 	CString editClipFolder = CGetSetOptions::GetPath(PATH_EDIT_CLIPS);
 	CString fullFilePath = editClipFolder + filePath;
-			
-	if (ReadFile(fullFilePath, unicode, unicodeText, utf8Text) == false)
+
+	nsPath::CPath path(filePath);
+	auto extenstion = path.GetExtension().MakeLower();
+
+	if (extenstion == _T("png") || extenstion == _T("bmp"))
 	{
-		Log(StrF(_T("Error reading file %s, clip id: %d, not saving"), fullFilePath, id));
+		if (ReadImageFile(fullFilePath, cf_dibBytes, pngBytes) == false)
+		{
+			Log(StrF(_T("Error reading image file %s, clip id: %d, not saving"), fullFilePath, id));
+			return false;
+		}
+	}
+	else if (ReadFile(fullFilePath, unicode, unicodeText, utf8Text) == false)
+	{
+		Log(StrF(_T("Error reading text file %s, clip id: %d, not saving"), fullFilePath, id));
 		return false;
 	}
 
 	if (id < 0 &&
 		unicodeText == _T("") &&
-		utf8Text == "")
+		utf8Text == "" &&
+		cf_dibBytes.size() <= 0 &&
+		pngBytes.size() <= 0)
 	{
-		Log(StrF(_T("Not saving new clip that is empty, path: %s, clip id: %d, not saving"), fullFilePath, id));
+		Log(StrF(_T("Not saving new clip that is empty, no text or image bytes, path: %s, clip id: %d, not saving"), fullFilePath, id));
 		return false;
 	}	
 
-	nsPath::CPath path(filePath);
-
 	BOOL modifyDescription = CGetSetOptions::GetUpdateDescWhenSavingClip();
-
-	auto extenstion = path.GetExtension().MakeLower();
-	if (extenstion == _T("txt"))
+	
+	if (extenstion == _T("bmp") || extenstion == _T("png"))
+	{		
+		clip.SaveFormats(nullptr, nullptr, nullptr, modifyDescription, &cf_dibBytes, &pngBytes);				
+	}
+	else if (extenstion == _T("txt"))
 	{
 		if (unicode)
 		{
@@ -289,7 +305,7 @@ bool CClipEditThread::SaveToClip(CString filePath, int id)
 		}
 		else
 		{
-			clip.SaveFormats(nullptr, nullptr, &utf8Text, modifyDescription);
+			clip.SaveFormats(nullptr, nullptr, &utf8Text, modifyDescription);			
 		}
 	}
 
@@ -352,6 +368,67 @@ bool CClipEditThread::ReadFile(CString filePath, bool &unicode, CString &unicode
 	return true;
 }
 
+std::vector<BYTE> CImageToPNGBytes(const CImage& image, REFGUID guidFileType)
+{
+	IStream* pStream = nullptr;
+	HRESULT hr = CreateStreamOnHGlobal(nullptr, TRUE, &pStream);
+	if (FAILED(hr)) {
+		return {};
+	}
+
+	ULARGE_INTEGER ulSize;
+
+	hr = image.Save(pStream, guidFileType);
+	if (FAILED(hr)) {
+		pStream->Release();
+		return {};
+	}
+
+	LARGE_INTEGER liZero = { 0 };
+	hr = pStream->Seek(liZero, STREAM_SEEK_SET, nullptr);
+	if (FAILED(hr)) {
+		pStream->Release();
+		return {};
+	}
+
+	hr = pStream->Seek({ 0 }, STREAM_SEEK_END, &ulSize);
+	if (FAILED(hr)) {
+		pStream->Release();
+		return {};
+	}
+
+	std::vector<BYTE> pngBytes((UINT)ulSize.QuadPart);
+
+	hr = pStream->Seek(liZero, STREAM_SEEK_SET, nullptr);
+	if (FAILED(hr)) {
+		pStream->Release();
+		return {};
+	}
+
+	hr = pStream->Read(pngBytes.data(), (UINT)ulSize.QuadPart, nullptr);
+	pStream->Release();
+
+	if (FAILED(hr)) {
+		return {};
+	}
+	return pngBytes;
+}
+
+bool CClipEditThread::ReadImageFile(CString path, std::vector<BYTE> &cf_dibBytes, std::vector<BYTE> & pngBytes)
+{
+	CImage image;
+	HRESULT hr = image.Load(path);
+	if (FAILED(hr)) 
+	{
+		Log(StrF(_T("Failed to load image, %s"), path));
+		return false;
+	}
+
+	pngBytes = CImageToPNGBytes(image, Gdiplus::ImageFormatPNG);	
+
+	return true;
+}
+
 BOOL CClipEditThread::GetTextFromRTF(CStringA rtf, CString &unicodeText)
 {
 	CConvertRTFToText cc;

+ 2 - 0
src/ClipEditThread.h

@@ -1,4 +1,5 @@
 #pragma once
+
 #include "EventThread.h"
 #include "Path.h"
 
@@ -18,6 +19,7 @@ private:
 	void OnFileChanged();
 	void OnTimeOut(void* param) override;
 	bool ReadFile(CString filePath, bool& unicode, CString& unicodeText, CStringA& utf8Text);
+	bool ReadImageFile(CString path, std::vector<BYTE>& cf_dibBytes, std::vector<BYTE>& pngBytes);
 	BOOL GetTextFromRTF(CStringA rtf, CString& unicodeText);
 	void RefreshWatch();
 	bool SaveToClip(CString filePath, int id);

+ 36 - 0
src/Options.cpp

@@ -88,6 +88,8 @@ CString CGetSetOptions::m_tempDragFileName = "";
 CTime CGetSetOptions::m_tempDragFileNameSetTime;
 BOOL CGetSetOptions::m_refreshViewAfterPasting = TRUE;
 BOOL CGetSetOptions::m_supportAllTypes = FALSE;
+int CGetSetOptions::m_clipEditSaveDelayAfterLoadSeconds = 3;
+int CGetSetOptions::m_clipEditSaveDelayAfterSaveSeconds = 3;
 
 
 CGetSetOptions::CGetSetOptions()
@@ -290,6 +292,8 @@ void CGetSetOptions::LoadSettings()
 	m_moveSelectionOnOpenHotkey = GetMoveSelectionOnOpenHotkey();
 	m_allowBackToBackDuplicates = GetAllowBackToBackDuplicates();
 	m_maintainSearchView = GetMaintainSearchView();
+	m_clipEditSaveDelayAfterLoadSeconds = GetClipEditSaveDelayAfterLoadSeconds();
+	m_clipEditSaveDelayAfterSaveSeconds = GetClipEditSaveDelayAfterSaveSeconds();
 
 	GetExtraNetworkPassword(true);
 
@@ -3093,6 +3097,16 @@ CString CGetSetOptions::GetTextEditorPath()
 	return GetProfileString("TextEditorPath", _T(""));
 }
 
+BOOL CGetSetOptions::SetImageEditorPath(CString path)
+{
+	return SetProfileString("ImageEditorPath", path);
+}
+
+CString CGetSetOptions::GetImageEditorPath()
+{
+	return GetProfileString("ImageEditorPath", _T(""));
+}
+
 BOOL CGetSetOptions::SetRTFEditorPath(CString path)
 {
 	return SetProfileString("RTFEditorPath", path);
@@ -3138,4 +3152,26 @@ void CGetSetOptions::SetPreferUtf8ForCompare(BOOL val)
 BOOL CGetSetOptions::GetPreferUtf8ForCompare()
 {
 	return GetProfileLong("PreferUtf8ForCompare", TRUE);
+}
+
+void CGetSetOptions::SetClipEditSaveDelayAfterLoadSeconds(int val)
+{
+	m_clipEditSaveDelayAfterLoadSeconds = val;
+	SetProfileLong("ClipEditSaveDelayAfterLoadSeconds", val);
+}
+
+int CGetSetOptions::GetClipEditSaveDelayAfterLoadSeconds()
+{
+	return GetProfileLong("ClipEditSaveDelayAfterLoadSeconds", 3);
+}
+
+void CGetSetOptions::SetClipEditSaveDelayAfterSaveSeconds(int val)
+{
+	m_clipEditSaveDelayAfterSaveSeconds = val;
+	SetProfileLong("ClipEditSaveDelayAfterSaveSeconds", val);
+}
+
+BOOL CGetSetOptions::GetClipEditSaveDelayAfterSaveSeconds()
+{
+	return GetProfileLong("ClipEditSaveDelayAfterSaveSeconds", 3);
 }

+ 11 - 0
src/Options.h

@@ -693,6 +693,9 @@ public:
 	static BOOL SetTextEditorPath(CString path);
 	static CString GetTextEditorPath();
 
+	static BOOL SetImageEditorPath(CString path);
+	static CString GetImageEditorPath();
+
 	static BOOL SetRTFEditorPath(CString path);
 	static CString GetRTFEditorPath();
 
@@ -704,6 +707,14 @@ public:
 
 	static void SetPreferUtf8ForCompare(BOOL val);
 	static BOOL GetPreferUtf8ForCompare();
+
+	static int	m_clipEditSaveDelayAfterLoadSeconds;
+	static void SetClipEditSaveDelayAfterLoadSeconds(int val);
+	static BOOL GetClipEditSaveDelayAfterLoadSeconds();
+
+	static int	m_clipEditSaveDelayAfterSaveSeconds;
+	static void SetClipEditSaveDelayAfterSaveSeconds(int val);
+	static BOOL GetClipEditSaveDelayAfterSaveSeconds();
 };
 
 // global for easy access and for initialization of fast access variables

+ 14 - 7
src/QPasteWnd.cpp

@@ -1200,7 +1200,7 @@ LRESULT CQPasteWnd::OnReloadClipInUI(WPARAM wParam, LPARAM lParam)
 	{
 		double order = q.getFloatField(_T("clipOrder"));
 		double orderGroup = q.getFloatField(_T("clipGroupOrder"));
-		int lastPasted = q.getInt64Field(_T("lastPasteDate"));
+		auto lastPasted = q.getInt64Field(_T("lastPasteDate"));
 		CString description = q.getStringField(_T("mText"));
 
 		std::vector<CMainTable>::iterator iter = m_listItems.begin();
@@ -1239,6 +1239,8 @@ LRESULT CQPasteWnd::OnReloadClipInUI(WPARAM wParam, LPARAM lParam)
 
 					foundClip = TRUE;
 
+					RemoveFromImageRtfCache(-1, clipId);
+
 					m_lstHeader.RefreshVisibleRows();
 					m_lstHeader.RedrawWindow();
 				}
@@ -2782,29 +2784,34 @@ bool CQPasteWnd::DeleteClips(CClipIDs& IDs, ARRAY& Indexs)
 	return true;
 }
 
-void CQPasteWnd::RemoveFromImageRtfCache(int id)
+void CQPasteWnd::RemoveFromImageRtfCache(int row, int id)
 {
 	ATL::CCritSecLock csLock(m_CritSection.m_sect);
 
-	CF_DibTypeMap::iterator iterDib = m_cf_dibCache.find(m_lstHeader.GetItemData(id));
+	if (id < 0)
+	{
+		id = m_lstHeader.GetItemData(row);
+	}
+
+	CF_DibTypeMap::iterator iterDib = m_cf_dibCache.find(id);
 	if (iterDib != m_cf_dibCache.end())
 	{
 		m_cf_dibCache.erase(iterDib);
 	}
 
-	CF_NoDibTypeMap::iterator iterNoDib = m_cf_NO_dibCache.find(m_lstHeader.GetItemData(id));
+	CF_NoDibTypeMap::iterator iterNoDib = m_cf_NO_dibCache.find(id);
 	if (iterNoDib != m_cf_NO_dibCache.end())
 	{
 		m_cf_NO_dibCache.erase(iterNoDib);
 	}
 
-	CF_DibTypeMap::iterator iterRtf = m_cf_rtfCache.find(m_lstHeader.GetItemData(id));
+	CF_DibTypeMap::iterator iterRtf = m_cf_rtfCache.find(id);
 	if (iterRtf != m_cf_rtfCache.end())
 	{
 		m_cf_rtfCache.erase(iterRtf);
 	}
 
-	CF_NoDibTypeMap::iterator iterNoRtf = m_cf_NO_rtfCache.find(m_lstHeader.GetItemData(id));
+	CF_NoDibTypeMap::iterator iterNoRtf = m_cf_NO_rtfCache.find(id);
 	if (iterNoRtf != m_cf_NO_rtfCache.end())
 	{
 		m_cf_NO_rtfCache.erase(iterNoRtf);
@@ -7188,7 +7195,7 @@ void CQPasteWnd::OnCustomSendToFriend(UINT idIn)
 void CQPasteWnd::OnChaiScriptPaste(UINT idIn)
 {
 	CSpecialPasteOptions pasteOptions;
-	int index = idIn - ChaiScriptMenuStartId;
+	UINT index = idIn - ChaiScriptMenuStartId;
 
 	if (index >= 0 &&
 		index < CGetSetOptions::m_pasteScripts.m_list.size())

+ 1 - 1
src/QPasteWnd.h

@@ -323,7 +323,7 @@ public:
 
 	bool ShowProperties(int id, int row);
 	bool DeleteClips(CClipIDs &IDs, ARRAY &Indexs);
-	void RemoveFromImageRtfCache(int id);
+	void RemoveFromImageRtfCache(int row, int id = -1);
 	bool SyncClipDataToArrayData(CClip &clip);
 	bool SelectIds(ARRAY &ids);