Browse Source

Added options to paste, upper, lower, captilize, sentance cases

ScottBrogden 9 years ago
parent
commit
e33e426da1
12 changed files with 511 additions and 51 deletions
  1. 4 0
      ActionEnums.h
  2. 9 1
      CP_Main.rc
  3. 1 1
      Clip.h
  4. 322 46
      OleClipSource.cpp
  5. 7 0
      OleClipSource.h
  6. 1 1
      ProcessPaste.cpp
  7. 139 0
      QPasteWnd.cpp
  8. 12 0
      QPasteWnd.h
  9. 6 1
      Resource.h
  10. 1 0
      Shared/IClip.h
  11. 3 0
      SpecialPasteOptions.cpp
  12. 6 1
      SpecialPasteOptions.h

+ 4 - 0
ActionEnums.h

@@ -48,6 +48,10 @@ public:
 		MOVE_CLIP_DOWN,
 		MOVE_CLIP_TOP,
 		FILTER_ON_SELECTED_CLIP,
+		PASTE_UPPER_CASE,
+		PASTE_LOWER_CASE,
+		PASTE_CAPITALiZE,
+		PASTE_SENTENCE_CASE,
 
 	};
 };

+ 9 - 1
CP_Main.rc

@@ -281,8 +281,16 @@ BEGIN
             MENUITEM "Prompt for IP",               32839,MFT_STRING,MFS_ENABLED
         END
         MENUITEM "View Full Description",       32793,MFT_STRING,MFS_ENABLED
+        POPUP "Special Paste",                  65535,MFT_STRING,MFS_ENABLED
+        BEGIN
+            MENUITEM "Plain Text Only",             32841,MFT_STRING,MFS_ENABLED
+            MENUITEM MFT_SEPARATOR
+            MENUITEM "UPPER CASE",                  ID_SPECIALPASTE_UPPERCASE,MFT_STRING,MFS_ENABLED
+            MENUITEM "lower case",                  ID_SPECIALPASTE_LOWERCASE,MFT_STRING,MFS_ENABLED
+            MENUITEM "Capitalize Case",             ID_SPECIALPASTE_CAPITALIZE,MFT_STRING,MFS_ENABLED
+            MENUITEM "Sentence case",               ID_SPECIALPASTE_SENTENCE,MFT_STRING,MFS_ENABLED
+        END
         MENUITEM "View Groups",                 32819,MFT_STRING,MFS_ENABLED
-        MENUITEM "Paste Plain Text Only",       32841,MFT_STRING,MFS_ENABLED
         POPUP "Compare",                        65535,MFT_STRING,MFS_ENABLED
         BEGIN
             MENUITEM "Select Left Text",            ID_COMPARE_SELECTLEFTCOMPARE,MFT_STRING,MFS_ENABLED

+ 1 - 1
Clip.h

@@ -45,7 +45,7 @@ public:
 	~CClipFormat();
 
 	void Clear();
-	void Free();
+	virtual void Free();
 
 	virtual CLIPFORMAT Type() { return m_cfType; }
 	virtual HGLOBAL Data() { return m_hgData; }

+ 322 - 46
OleClipSource.cpp

@@ -53,8 +53,8 @@ BOOL COleClipSource::DoImmediateRender()
 	INT_PTR count = m_ClipIDs.GetSize();
 	if(count <= 0)
 		return 0;
-
-	BOOL bProcessedMult = FALSE;
+	
+	CClip clip;
 
 	if(count > 1)
 	{
@@ -62,103 +62,374 @@ BOOL COleClipSource::DoImmediateRender()
 		CCF_TextAggregator CFText(SepA);
 		if(m_ClipIDs.AggregateData(CFText, CF_TEXT, g_Opt.m_bMultiPasteReverse))
 		{
-			CacheGlobalData(CF_TEXT, CFText.GetHGlobal());
-			bProcessedMult = TRUE;
+			CClipFormat cf(CF_TEXT, CFText.GetHGlobal());
+			clip.m_Formats.Add(cf);
+			//clip.m_Formats now owns the global data
+			cf.m_autoDeleteData = false;
 		}
 
 		CStringW SepW = CTextConvert::ConvertToUnicode(g_Opt.GetMultiPasteSeparator());
 		CCF_UnicodeTextAggregator CFUnicodeText(SepW);
 		if(m_ClipIDs.AggregateData(CFUnicodeText, CF_UNICODETEXT, g_Opt.m_bMultiPasteReverse))
 		{
-			CacheGlobalData(CF_UNICODETEXT, CFUnicodeText.GetHGlobal());
-			bProcessedMult = TRUE;
+			CClipFormat cf(CF_UNICODETEXT, CFUnicodeText.GetHGlobal());
+			clip.m_Formats.Add(cf);
+			//clip.m_Formats now owns the global data
+			cf.m_autoDeleteData = false;
 		}
 
-		if (m_pasteOptions.m_pasteAsPlainText &&
-			bProcessedMult == FALSE)
+		if ((m_pasteOptions.LimitFormatsToText()) &&
+			clip.m_Formats.GetCount() == 0)
 		{
 			CCF_HDropAggregator HDrop;
 			if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
 			{
-				CacheGlobalData(CF_UNICODETEXT, HDrop.GetHGlobalAsString());
-				bProcessedMult = TRUE;
+				CClipFormat cf(CF_UNICODETEXT, HDrop.GetHGlobalAsString());
+				clip.m_Formats.Add(cf);
+				//clip.m_Formats now owns the global data
+				cf.m_autoDeleteData = false;
 			}
 		}
-		else if(m_pasteOptions.m_pasteAsPlainText == false)
+		else if (m_pasteOptions.LimitFormatsToText() == false)
 		{
 			CCF_HDropAggregator HDrop;
 			if(m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
 			{
-				CacheGlobalData(CF_HDROP, HDrop.GetHGlobal());
-				bProcessedMult = TRUE;
+				CClipFormat cf(CF_HDROP, HDrop.GetHGlobal());
+				clip.m_Formats.Add(cf);
+				//clip.m_Formats now owns the global data
+				cf.m_autoDeleteData = false;
 			}
 
 			CRichTextAggregator RichText(SepA);
 			if(m_ClipIDs.AggregateData(RichText, theApp.m_RTFFormat, g_Opt.m_bMultiPasteReverse))
 			{
-				CacheGlobalData(theApp.m_RTFFormat, RichText.GetHGlobal());
-				bProcessedMult = TRUE;
+				CClipFormat cf(theApp.m_RTFFormat, RichText.GetHGlobal());
+				clip.m_Formats.Add(cf);
+				//clip.m_Formats now owns the global data
+				cf.m_autoDeleteData = false;
 			}
 
 			CHTMLFormatAggregator Html(SepA);
 			if(m_ClipIDs.AggregateData(Html, theApp.m_HTML_Format, g_Opt.m_bMultiPasteReverse))
 			{
-				CacheGlobalData(theApp.m_HTML_Format, Html.GetHGlobal());
-				bProcessedMult = TRUE;
+				CClipFormat cf(theApp.m_HTML_Format, Html.GetHGlobal());
+				clip.m_Formats.Add(cf);
+				//clip.m_Formats now owns the global data
+				cf.m_autoDeleteData = false;
 			}
 		}
 	}
 
-	if(count >= 1 && bProcessedMult == FALSE)
+	if (count >= 1 && clip.m_Formats.GetCount() == 0)
 	{
-		CClip clip;
-		CClipFormats formats;
+		clip.LoadFormats(m_ClipIDs[0], m_pasteOptions.LimitFormatsToText());
+	}
+
+	if (m_pasteOptions.LimitFormatsToText())
+	{
+		PlainTextFilter(clip);
+	}
+
+	if(m_pasteOptions.m_pasteUpperCase ||
+		m_pasteOptions.m_pasteLowerCase)
+	{
+		DoUpperLowerCase(clip, m_pasteOptions.m_pasteUpperCase);
+	}
+	else if(m_pasteOptions.m_pasteCapitalize)
+	{
+		Capitalize(clip);
+	}
+	else if(m_pasteOptions.m_pasteSentenceCase)
+	{
+		SentenceCase(clip);
+	}
+
+	return PutFormatOnClipboard(&clip.m_Formats) > 0;
+}
+
+void COleClipSource::DoUpperLowerCase(CClip &clip, bool upper)
+{
+	IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
+	if (unicodeTextFormat != NULL)
+	{
+		HGLOBAL data = unicodeTextFormat->Data();
+		wchar_t * stringData = (wchar_t *) GlobalLock(data);
+		int size = (int) GlobalSize(data);
+		CString cs(stringData, (size / sizeof(wchar_t)));
+		GlobalUnlock(data);
 
-		clip.LoadFormats(m_ClipIDs[0], m_pasteOptions.m_pasteAsPlainText);
+		//free the old text we are going to replace it below with an upper case version
+		unicodeTextFormat->Free();
 
-		if(m_pasteOptions.m_pasteAsPlainText)
+		CString val;
+		if (upper)
 		{
-			bool foundText = false;
-			INT_PTR hDropIndex = -1;
-			INT_PTR	count = clip.m_Formats.GetCount();
-			for (INT_PTR i = 0; i < count; i++)
-			{
-				CClipFormat *pCF = &clip.m_Formats.ElementAt(i);
+			val = cs.MakeUpper();
+		}
+		else
+		{
+			val = cs.MakeLower();
+		}
+		
+		long lLen = val.GetLength();
+		HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((lLen+1) * sizeof(wchar_t)));
+		val.ReleaseBuffer();
+
+		unicodeTextFormat->Data(hGlobal);		
+	}
+
+	IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
+	if (asciiTextFormat != NULL)
+	{
+		HGLOBAL data = asciiTextFormat->Data();
+		char * stringData = (char *) GlobalLock(data);
+		int size = (int) GlobalSize(data);
+		CStringA cs(stringData, size);
+		GlobalUnlock(data);
+
+		//free the old text we are going to replace it below with an upper case version
+		asciiTextFormat->Free();
+		
+		CString val;
+		if (upper)
+		{
+			val = cs.MakeUpper();
+		}
+		else
+		{
+			val = cs.MakeLower();
+		}
+
+		long lLen = val.GetLength();
+		HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(lLen), lLen + sizeof(char));
+		val.ReleaseBuffer();
 
-				if (pCF->m_cfType == CF_TEXT ||
-					pCF->m_cfType == CF_UNICODETEXT)
+		asciiTextFormat->Data(hGlobal);
+	}
+}
+
+void COleClipSource::Capitalize(CClip &clip)
+{
+	IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
+	if (unicodeTextFormat != NULL)
+	{
+		HGLOBAL data = unicodeTextFormat->Data();
+		wchar_t * stringData = (wchar_t *) GlobalLock(data);
+		int size = (int) GlobalSize(data);
+		CString cs(stringData, (size / sizeof(wchar_t)));
+		GlobalUnlock(data);
+
+		//free the old text we are going to replace it below with an upper case version
+		unicodeTextFormat->Free();
+
+		CString val = cs.MakeLower();		
+		long len = val.GetLength();
+
+		if (len > 0)
+		{
+			wchar_t * pText = val.GetBuffer();
+			
+			pText[0] = toupper(pText[0]);
+			bool capitalize = false;
+			
+			for (int i = 1; i < len; i++)
+			{
+				wchar_t item = pText[i];
+				if (item == ' ')
 				{
-					foundText = true;
+					capitalize = true;
 				}
-				else if(pCF->m_cfType == CF_HDROP)
+				else if (capitalize)
 				{
-					hDropIndex = i;
+					pText[i] = toupper(item);
+					capitalize = false;
 				}
 			}
+		}
+		
+		val.ReleaseBuffer();
+
+		HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
+
+		unicodeTextFormat->Data(hGlobal);
+	}
+
+	IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
+	if (asciiTextFormat != NULL)
+	{
+		HGLOBAL data = asciiTextFormat->Data();
+		char * stringData = (char *) GlobalLock(data);
+		int size = (int) GlobalSize(data);
+		CStringA cs(stringData, size);
+		GlobalUnlock(data);
 
-			if(foundText &&
-				hDropIndex > -1)
+		//free the old text we are going to replace it below with an upper case version
+		asciiTextFormat->Free();
+
+		CStringA val = cs.MakeLower();
+		long len = val.GetLength();
+
+		if (len > 0)
+		{
+			char * pText = val.GetBuffer();
+
+			pText[0] = toupper(pText[0]);
+			bool capitalize = false;
+
+			for (int i = 1; i < len; i++)
 			{
-				clip.m_Formats.RemoveAt(hDropIndex);
+				wchar_t item = pText[i];
+				if (item == ' ')
+				{
+					capitalize = true;
+				}
+				else if (capitalize)
+				{
+					pText[i] = toupper(item);
+					capitalize = false;
+				}
 			}
-			else if(foundText == false &&
-					hDropIndex > -1)
+		}
+
+		val.ReleaseBuffer();
+
+		HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), (len + 1));
+
+		asciiTextFormat->Data(hGlobal);
+	}
+}
+
+void COleClipSource::SentenceCase(CClip &clip)
+{
+	IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
+	if (unicodeTextFormat != NULL)
+	{
+		HGLOBAL data = unicodeTextFormat->Data();
+		wchar_t * stringData = (wchar_t *) GlobalLock(data);
+		int size = (int) GlobalSize(data);
+		CString cs(stringData, (size / sizeof(wchar_t)));
+		GlobalUnlock(data);
+
+		//free the old text we are going to replace it below with an upper case version
+		unicodeTextFormat->Free();
+
+		CString val = cs.MakeLower();
+		long len = val.GetLength();
+
+		if (len > 0)
+		{
+			wchar_t * pText = val.GetBuffer();
+
+			pText[0] = toupper(pText[0]);
+			bool capitalize = false;
+
+			for (int i = 1; i < len; i++)
 			{
-				CCF_HDropAggregator HDrop;
-				if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
+				wchar_t item = pText[i];
+				if (item == '.' ||
+					item == '!' ||
+					item == '?')
+				{
+					capitalize = true;
+				}
+				else if (capitalize && item != ' ')
 				{
-					CacheGlobalData(CF_UNICODETEXT, HDrop.GetHGlobalAsString());
+					pText[i] = toupper(item);
+					capitalize = false;
+				}
+			}
+		}
+
+
+		val.ReleaseBuffer();
+
+		HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
+
+		unicodeTextFormat->Data(hGlobal);
+	}
+
+	IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
+	if (asciiTextFormat != NULL)
+	{
+		HGLOBAL data = asciiTextFormat->Data();
+		char * stringData = (char *) GlobalLock(data);
+		int size = (int) GlobalSize(data);
+		CStringA cs(stringData, size);
+		GlobalUnlock(data);
+
+		//free the old text we are going to replace it below with an upper case version
+		asciiTextFormat->Free();
 
-					return 1;
+		CStringA val = cs.MakeLower();
+		long len = val.GetLength();
+
+		if (len > 0)
+		{
+			char * pText = val.GetBuffer();
+
+			pText[0] = toupper(pText[0]);
+			bool capitalize = false;
+
+			for (int i = 1; i < len; i++)
+			{
+				wchar_t item = pText[i];
+				if (item == '.' ||
+					item == '!' ||
+					item == '?')
+				{
+					capitalize = true;
+				}
+				else if (capitalize && item != ' ')
+				{
+					pText[i] = toupper(item);
+					capitalize = false;
 				}
 			}
+		}
+
+		val.ReleaseBuffer();
 
+		HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), (len + 1));
+
+		asciiTextFormat->Data(hGlobal);
+	}
+}
+
+void COleClipSource::PlainTextFilter(CClip &clip)
+{
+	bool foundText = false;
+	INT_PTR hDropIndex = -1;
+	INT_PTR	count = clip.m_Formats.GetCount();
+	for (INT_PTR i = 0; i < count; i++)
+	{
+		CClipFormat *pCF = &clip.m_Formats.ElementAt(i);
+
+		if (pCF->m_cfType == CF_TEXT ||
+			pCF->m_cfType == CF_UNICODETEXT)
+		{
+			foundText = true;
 		}
-		
-		return PutFormatOnClipboard(&clip.m_Formats) > 0;
-	}		
+		else if (pCF->m_cfType == CF_HDROP)
+		{
+			hDropIndex = i;
+		}
+	}
 
-	return bProcessedMult;
+	if (foundText &&
+		hDropIndex > -1)
+	{
+		clip.m_Formats.RemoveAt(hDropIndex);
+	}
+	else if (foundText == false &&
+		hDropIndex > -1)
+	{
+		CCF_HDropAggregator HDrop;
+		if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
+		{
+			clip.m_Formats.Add(CClipFormat(CF_UNICODETEXT, HDrop.GetHGlobalAsString()));
+		}
+	}
 }
 
 INT_PTR COleClipSource::PutFormatOnClipboard(CClipFormats *pFormats)
@@ -197,6 +468,11 @@ INT_PTR COleClipSource::PutFormatOnClipboard(CClipFormats *pFormats)
 			continue;
 		}
 
+		wchar_t * stringData = (wchar_t *) GlobalLock(pCF->m_hgData);
+		int size = (int) GlobalSize(pCF->m_hgData);
+		CString cs(stringData, (size / sizeof(wchar_t)));
+		GlobalUnlock(pCF->m_hgData);
+
 		Log(StrF(_T("Setting clipboard type: %s to the clipboard"), GetFormatName(pCF->m_cfType)));
 
 		CacheGlobalData(pCF->m_cfType, pCF->m_hgData);

+ 7 - 0
OleClipSource.h

@@ -20,6 +20,9 @@ public:
 
 	BOOL DoDelayRender();
 	BOOL DoImmediateRender();
+
+	void PlainTextFilter(CClip &clip);
+
 	INT_PTR PutFormatOnClipboard(CClipFormats *pFormats);
 
 public:
@@ -27,4 +30,8 @@ public:
 
 protected:
 	CClipFormats m_DelayRenderedFormats;
+
+	void DoUpperLowerCase(CClip &clip, bool upper);
+	void Capitalize(CClip &clip);
+	void SentenceCase(CClip &clip);;
 };

+ 1 - 1
ProcessPaste.cpp

@@ -35,7 +35,7 @@ BOOL CProcessPaste::DoPaste()
 		
 		// Ignore the clipboard change that we will cause IF:
 		// 1) we are pasting a single element, since the element is already
-		//    in the db and its lDate was updated by MarkAsPasted().
+		//    in the db and its lDate was updated by MarkAsPas???ted().
 		// OR
 		// 2) we are pasting multiple, but g_Opt.m_bSaveMultiPaste is false
 		if(GetClipIDs().GetSize() == 1 || !g_Opt.m_bSaveMultiPaste)

+ 139 - 0
QPasteWnd.cpp

@@ -244,6 +244,14 @@ ON_COMMAND(ID_MENU_FILTERON, &CQPasteWnd::OnMenuFilteron)
 ON_UPDATE_COMMAND_UI(ID_MENU_FILTERON, &CQPasteWnd::OnUpdateMenuFilteron)
 ON_BN_CLICKED(ON_TOP_WARNING, OnAlwaysOnTopClicked)
 //ON_WM_CTLCOLOR()
+ON_COMMAND(ID_SPECIALPASTE_UPPERCASE, &CQPasteWnd::OnSpecialpasteUppercase)
+ON_UPDATE_COMMAND_UI(ID_SPECIALPASTE_UPPERCASE, &CQPasteWnd::OnUpdateSpecialpasteUppercase)
+ON_COMMAND(ID_SPECIALPASTE_LOWERCASE, &CQPasteWnd::OnSpecialpasteLowercase)
+ON_UPDATE_COMMAND_UI(ID_SPECIALPASTE_LOWERCASE, &CQPasteWnd::OnUpdateSpecialpasteLowercase)
+ON_COMMAND(ID_SPECIALPASTE_CAPITALIZE, &CQPasteWnd::OnSpecialpasteCapitalize)
+ON_UPDATE_COMMAND_UI(ID_SPECIALPASTE_CAPITALIZE, &CQPasteWnd::OnUpdateSpecialpasteCapitalize)
+ON_COMMAND(ID_SPECIALPASTE_SENTENCE, &CQPasteWnd::OnSpecialpasteSentence)
+ON_UPDATE_COMMAND_UI(ID_SPECIALPASTE_SENTENCE, &CQPasteWnd::OnUpdateSpecialpasteSentence)
 END_MESSAGE_MAP()
 
 
@@ -2723,6 +2731,18 @@ bool CQPasteWnd::DoAction(DWORD actionId)
 	case ActionEnums::FILTER_ON_SELECTED_CLIP:
 		ret = DoFilterOnSelectedClip();
 		break;
+	case ActionEnums::PASTE_UPPER_CASE:
+		ret = DoPasteUpperCase();
+		break;
+	case ActionEnums::PASTE_LOWER_CASE:
+		ret = DoPasteLowerCase();
+		break;
+	case ActionEnums::PASTE_CAPITALiZE:
+		ret = DoPasteCapitalize();
+		break;
+	case ActionEnums::PASTE_SENTENCE_CASE:
+		ret = DoPasteSentenceCase();
+		break;
 	}
 
 	return ret;
@@ -3740,6 +3760,58 @@ bool CQPasteWnd::DoFilterOnSelectedClip()
 	return ret;
 }
 
+bool CQPasteWnd::DoPasteUpperCase()
+{
+	if (::GetFocus() == m_lstHeader.GetSafeHwnd())
+	{
+		CSpecialPasteOptions pasteOptions;
+		pasteOptions.m_pasteUpperCase = true;
+		OpenSelection(pasteOptions);
+		return true;
+	}
+
+	return false;
+}
+
+bool CQPasteWnd::DoPasteLowerCase()
+{
+	if (::GetFocus() == m_lstHeader.GetSafeHwnd())
+	{
+		CSpecialPasteOptions pasteOptions;
+		pasteOptions.m_pasteLowerCase = true;
+		OpenSelection(pasteOptions);
+		return true;
+	}
+
+	return false;
+}
+
+bool CQPasteWnd::DoPasteCapitalize()
+{
+	if (::GetFocus() == m_lstHeader.GetSafeHwnd())
+	{
+		CSpecialPasteOptions pasteOptions;
+		pasteOptions.m_pasteCapitalize = true;
+		OpenSelection(pasteOptions);
+		return true;
+	}
+
+	return false;
+}
+
+bool CQPasteWnd::DoPasteSentenceCase()
+{
+	if (::GetFocus() == m_lstHeader.GetSafeHwnd())
+	{
+		CSpecialPasteOptions pasteOptions;
+		pasteOptions.m_pasteSentenceCase = true;
+		OpenSelection(pasteOptions);
+		return true;
+	}
+
+	return false;
+}
+
 bool CQPasteWnd::DoExportToBitMapFile()
 {
 	bool ret = false;
@@ -5197,3 +5269,70 @@ void CQPasteWnd::OnAlwaysOnTopClicked()
 {
 	DoAction(ActionEnums::TOGGLESHOWPERSISTANT);
 }
+
+
+void CQPasteWnd::OnSpecialpasteUppercase()
+{
+	DoAction(ActionEnums::PASTE_UPPER_CASE);
+}
+
+
+void CQPasteWnd::OnUpdateSpecialpasteUppercase(CCmdUI *pCmdUI)
+{
+	if (!pCmdUI->m_pMenu)
+	{
+		return;
+	}
+
+	UpdateMenuShortCut(pCmdUI, ActionEnums::PASTE_UPPER_CASE);
+}
+
+
+void CQPasteWnd::OnSpecialpasteLowercase()
+{
+	DoAction(ActionEnums::PASTE_LOWER_CASE);
+}
+
+
+void CQPasteWnd::OnUpdateSpecialpasteLowercase(CCmdUI *pCmdUI)
+{
+	if (!pCmdUI->m_pMenu)
+	{
+		return;
+	}
+
+	UpdateMenuShortCut(pCmdUI, ActionEnums::PASTE_LOWER_CASE);
+}
+
+
+void CQPasteWnd::OnSpecialpasteCapitalize()
+{
+	DoAction(ActionEnums::PASTE_CAPITALiZE);
+}
+
+void CQPasteWnd::OnUpdateSpecialpasteCapitalize(CCmdUI *pCmdUI)
+{
+	if (!pCmdUI->m_pMenu)
+	{
+		return;
+	}
+
+	UpdateMenuShortCut(pCmdUI, ActionEnums::PASTE_CAPITALiZE);
+}
+
+
+void CQPasteWnd::OnSpecialpasteSentence()
+{
+	DoAction(ActionEnums::PASTE_SENTENCE_CASE);
+}
+
+
+void CQPasteWnd::OnUpdateSpecialpasteSentence(CCmdUI *pCmdUI)
+{
+	if (!pCmdUI->m_pMenu)
+	{
+		return;
+	}
+
+	UpdateMenuShortCut(pCmdUI, ActionEnums::PASTE_SENTENCE_CASE);
+}

+ 12 - 0
QPasteWnd.h

@@ -243,6 +243,10 @@ public:
 	bool DoMoveClipUp();
 	bool DoMoveClipTOP();
 	bool DoFilterOnSelectedClip();
+	bool DoPasteUpperCase();
+	bool DoPasteLowerCase();
+	bool DoPasteCapitalize();
+	bool DoPasteSentenceCase();
 
 	void UpdateMenuShortCut(CCmdUI *pCmdUI, DWORD action);
 
@@ -419,4 +423,12 @@ public:
 	afx_msg void OnUpdateMenuFilteron(CCmdUI *pCmdUI);
 	afx_msg void OnAlwaysOnTopClicked();
 	//afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnSpecialpasteUppercase();
+	afx_msg void OnUpdateSpecialpasteUppercase(CCmdUI *pCmdUI);
+	afx_msg void OnSpecialpasteLowercase();
+	afx_msg void OnUpdateSpecialpasteLowercase(CCmdUI *pCmdUI);
+	afx_msg void OnSpecialpasteCapitalize();
+	afx_msg void OnUpdateSpecialpasteCapitalize(CCmdUI *pCmdUI);
+	afx_msg void OnSpecialpasteSentence();
+	afx_msg void OnUpdateSpecialpasteSentence(CCmdUI *pCmdUI);
 };

+ 6 - 1
Resource.h

@@ -516,6 +516,11 @@
 #define ID_CLIPORDER_MOVETOTOP          32908
 #define ID_FIRST_FIXUPSTICKYCLIPORDER   32909
 #define ID_MENU_FILTERON                32910
+#define ID_MENU_SPECIALPASTE            32911
+#define ID_SPECIALPASTE_UPPERCASE       32912
+#define ID_SPECIALPASTE_LOWERCASE       32913
+#define ID_SPECIALPASTE_CAPITALIZE      32914
+#define ID_SPECIALPASTE_SENTENCE        32915
 
 // Next default values for new objects
 // 
@@ -523,7 +528,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_3D_CONTROLS                     1
 #define _APS_NEXT_RESOURCE_VALUE        240
-#define _APS_NEXT_COMMAND_VALUE         32911
+#define _APS_NEXT_COMMAND_VALUE         32916
 #define _APS_NEXT_CONTROL_VALUE         2127
 #define _APS_NEXT_SYMED_VALUE           101
 #endif

+ 1 - 0
Shared/IClip.h

@@ -12,6 +12,7 @@ public:
 	virtual void Type(CLIPFORMAT type) = 0;
 	virtual void Data(HGLOBAL data) = 0;
 	virtual void AutoDeleteData(bool autoDelete) = 0;
+	virtual void Free() = 0;
 };
 
 //Contains a list of IClipFormats

+ 3 - 0
SpecialPasteOptions.cpp

@@ -6,6 +6,9 @@ CSpecialPasteOptions::CSpecialPasteOptions()
 {
 	m_pasteAsPlainText = false;
 	m_pPasteFormats = NULL;
+	m_pasteUpperCase = false;
+	m_pasteLowerCase = false;
+	m_pasteCapitalize = false;
 }
 
 

+ 6 - 1
SpecialPasteOptions.h

@@ -8,9 +8,14 @@ public:
 	~CSpecialPasteOptions();
 
 	bool m_pasteAsPlainText;
-	bool m_pasteRTFNoTextHighlight;
+	bool m_pasteUpperCase;
+	bool m_pasteLowerCase;
+	bool m_pasteCapitalize;
+	bool m_pasteSentenceCase;
 	CClipFormats *m_pPasteFormats;
 
+	bool LimitFormatsToText() { return m_pasteAsPlainText || m_pasteUpperCase || m_pasteLowerCase || m_pasteCapitalize || m_pasteSentenceCase; }
+
 	CString ToString();
 };