ProcessPaste.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include "stdafx.h"
  2. #include "CP_Main.h"
  3. #include "ProcessPaste.h"
  4. #ifdef _DEBUG
  5. #undef THIS_FILE
  6. static char THIS_FILE[]=__FILE__;
  7. #define new DEBUG_NEW
  8. #endif
  9. /*------------------------------------------------------------------*\
  10. Globals
  11. \*------------------------------------------------------------------*/
  12. BOOL MarkClipAsPasted(long lID)
  13. {
  14. CGetSetOptions::SetTripPasteCount(-1);
  15. CGetSetOptions::SetTotalPasteCount(-1);
  16. if( !g_Opt.m_bUpdateTimeOnPaste )
  17. return FALSE;
  18. try
  19. {
  20. //Update the time it was copied so that it appears at the top of the
  21. //paste list. Items are sorted by this time.
  22. CMainTable ctMain;
  23. ctMain.Open("SELECT * FROM Main WHERE lID = %d", lID);
  24. ctMain.Edit();
  25. CTime now = CTime::GetCurrentTime();
  26. ctMain.m_lDate = (long)now.GetTime();
  27. ctMain.Update();
  28. ctMain.Close();
  29. return TRUE;
  30. }
  31. catch(CDaoException *e)
  32. {
  33. ASSERT(FALSE);
  34. e->Delete();
  35. }
  36. return FALSE;
  37. }
  38. /*------------------------------------------------------------------*\
  39. CClipIDs
  40. \*------------------------------------------------------------------*/
  41. //-------------------
  42. // PASTING FUNCTIONS
  43. //-------------------
  44. // allocate an HGLOBAL of the given Format Type representing these Clip IDs.
  45. HGLOBAL CClipIDs::Render( UINT cfType )
  46. {
  47. int count = GetSize();
  48. if( count <= 0 )
  49. return 0;
  50. if( count == 1 )
  51. return CClip::LoadFormat( GetAt(0), cfType );
  52. CString text = AggregateText( CF_TEXT, "\r\n" );
  53. return NewGlobalP( (void*)(LPCSTR) text, text.GetLength()+1 );
  54. }
  55. void CClipIDs::GetTypes( CClipTypes& types )
  56. {
  57. int count = GetSize();
  58. types.RemoveAll();
  59. if( count > 1 )
  60. types.Add( CF_TEXT );
  61. else if( count == 1 )
  62. CClip::LoadTypes( GetAt(0), types );
  63. }
  64. // Aggregates the cfType Format Data of the Clip IDs in this array, assuming
  65. // each Format is NULL terminated and placing pSeparator between them.
  66. // This assumes that the given cfType is a null terminated text type.
  67. CString CClipIDs::AggregateText( UINT cfType, char* pSeparator )
  68. {
  69. CString csSQL;
  70. CDataTable recset;
  71. CString text;
  72. char* pData = NULL;
  73. DWORD len;
  74. DWORD maxLen;
  75. // maybe we should sum up the "recset.m_ooData.m_dwDataLength" of all IDs first
  76. // in order to determine the max space required??? Or would that be wastefull?
  77. // allocate a large initial buffer to minimize realloc for concatenations
  78. text.GetBuffer(1000);
  79. text.ReleaseBuffer(0);
  80. int numIDs = GetSize();
  81. int* pIDs = GetData();
  82. csSQL.Format("SELECT * FROM Data WHERE strClipBoardFormat = \'%s\' AND lParentID = %%d", GetFormatName(cfType));
  83. try
  84. {
  85. for( int i=0; i < numIDs; i++ )
  86. {
  87. recset.Open( csSQL, pIDs[i] );
  88. if( !recset.IsBOF() && !recset.IsEOF() )
  89. {
  90. maxLen = recset.m_ooData.m_dwDataLength;
  91. if( maxLen == 0 )
  92. continue;
  93. pData = (char*) GlobalLock(recset.m_ooData.m_hData);
  94. ASSERT( pData );
  95. // verify that pData is null terminated
  96. // do a quick check to see if the last character is null
  97. if( pData[maxLen-1] != '\0' )
  98. {
  99. for( len=0; len < maxLen && pData[len] != '\0'; len++ ) {}
  100. // if it is not null terminated, skip this item
  101. if( len >= maxLen )
  102. continue;
  103. }
  104. text += pData;
  105. GlobalUnlock(recset.m_ooData.m_hData);
  106. if( pSeparator )
  107. text += pSeparator;
  108. }
  109. recset.Close();
  110. }
  111. }
  112. CATCHDAO
  113. return text;
  114. }
  115. /*------------------------------------------------------------------*\
  116. COleClipSource
  117. \*------------------------------------------------------------------*/
  118. //IMPLEMENT_DYNAMIC(COleClipSource, COleDataSource)
  119. COleClipSource::COleClipSource()
  120. {
  121. }
  122. COleClipSource::~COleClipSource()
  123. {
  124. }
  125. BOOL COleClipSource::DoDelayRender()
  126. {
  127. CClipTypes types;
  128. m_ClipIDs.GetTypes( types );
  129. int count = types.GetSize();
  130. for( int i=0; i < count; i++ )
  131. DelayRenderData( types[i] );
  132. return count;
  133. }
  134. BOOL COleClipSource::DoImmediateRender()
  135. {
  136. int count = m_ClipIDs.GetSize();
  137. if( count <= 0 )
  138. return 0;
  139. if( count == 1 )
  140. {
  141. CClipFormats formats;
  142. CClipFormat* pCF;
  143. CClip::LoadFormats( m_ClipIDs[0], formats );
  144. count = formats.GetSize(); // reusing "count"
  145. for( int i=0; i < count; i++ )
  146. {
  147. pCF = &formats[i];
  148. CacheGlobalData( pCF->m_cfType, pCF->m_hgData );
  149. pCF->m_hgData = 0; // OLE owns it now
  150. }
  151. formats.RemoveAll();
  152. return count;
  153. }
  154. HGLOBAL hGlobal;
  155. CString text = m_ClipIDs.AggregateText( CF_TEXT, "\r\n" );
  156. hGlobal = NewGlobalP( (void*)(LPCSTR) text, text.GetLength()+1 );
  157. CacheGlobalData( CF_TEXT, hGlobal );
  158. return hGlobal != 0;
  159. }
  160. BEGIN_MESSAGE_MAP(COleClipSource, COleDataSource)
  161. END_MESSAGE_MAP()
  162. // COleClipSource message handlers
  163. BOOL COleClipSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  164. {
  165. HGLOBAL hData = m_ClipIDs.Render( lpFormatEtc->cfFormat );
  166. if( !hData )
  167. return FALSE;
  168. // if phGlobal is null, we can just give the allocated mem
  169. // else, our data must fit within the GlobalSize(*phGlobal)
  170. if( *phGlobal == 0 )
  171. *phGlobal = hData;
  172. else
  173. {
  174. UINT len = min( ::GlobalSize(*phGlobal), ::GlobalSize(hData) );
  175. if( len )
  176. CopyToGlobalHH( *phGlobal, hData, len );
  177. ::GlobalFree( hData );
  178. }
  179. return TRUE;
  180. }
  181. /*------------------------------------------------------------------*\
  182. CProcessPaste
  183. \*------------------------------------------------------------------*/
  184. CProcessPaste::CProcessPaste() : m_bDeleteOle(true)
  185. {
  186. m_pOle = new COleClipSource;
  187. }
  188. CProcessPaste::~CProcessPaste()
  189. {
  190. if( m_bDeleteOle )
  191. delete m_pOle;
  192. }
  193. BOOL CProcessPaste::DoPaste()
  194. {
  195. if( m_pOle->DoImmediateRender() )
  196. {
  197. // if we are pasting a single element, do not handle clipboard data change
  198. // (the element is already in the db and its lDate is updated by MarkAsPasted())
  199. if( GetClipIDs().GetSize() == 1 )
  200. {
  201. m_pOle->CacheGlobalData(theApp.m_cfIgnoreClipboard, NewGlobalP("Ignore", 8));
  202. m_pOle->SetClipboard();
  203. }
  204. else // we are pasting a new aggregate text
  205. {
  206. if( g_Opt.m_bSaveMultiPaste )
  207. m_pOle->SetClipboard();
  208. else
  209. {
  210. m_pOle->CacheGlobalData(theApp.m_cfIgnoreClipboard, NewGlobalP("Ignore", 8));
  211. m_pOle->SetClipboard();
  212. }
  213. }
  214. m_bDeleteOle = false; // m_pOle is managed by the OLE clipboard now
  215. theApp.SendPaste();
  216. MarkAsPasted();
  217. return TRUE;
  218. }
  219. return FALSE;
  220. }
  221. BOOL CProcessPaste::DoDrag()
  222. {
  223. m_pOle->DoDelayRender();
  224. DROPEFFECT de = m_pOle->DoDragDrop( DROPEFFECT_COPY );
  225. if( de != DROPEFFECT_NONE )
  226. {
  227. MarkAsPasted();
  228. return TRUE;
  229. }
  230. return FALSE;
  231. }
  232. void CProcessPaste::MarkAsPasted()
  233. {
  234. CClipIDs& clips = GetClipIDs();
  235. if( clips.GetSize() == 1 )
  236. MarkClipAsPasted( clips.GetAt(0) );
  237. }