ProcessCopy.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. // ProcessCopy.cpp: implementation of the CProcessCopy class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "CP_Main.h"
  6. #include "ProcessCopy.h"
  7. #include "DatabaseUtilities.h"
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. HGLOBAL COleDataObjectEx::GetGlobalData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
  14. {
  15. bool bRet = theApp.m_bHandleClipboardDataChange;
  16. theApp.m_bHandleClipboardDataChange = false;
  17. HGLOBAL global = COleDataObject::GetGlobalData(cfFormat, lpFormatEtc);
  18. theApp.m_bHandleClipboardDataChange = bRet;
  19. return global;
  20. }
  21. //////////////////////////////////////////////////////////////////////
  22. // Construction/Destruction
  23. //////////////////////////////////////////////////////////////////////
  24. CProcessCopy::CProcessCopy()
  25. {
  26. InitializeCriticalSection(&m_CriticalSection);
  27. }
  28. CProcessCopy::~CProcessCopy()
  29. {
  30. DeleteCriticalSection(&m_CriticalSection);
  31. }
  32. #define EXIT_DO_COPY(ret) { m_oleData.Release(); LeaveCriticalSection(&m_CriticalSection); return(ret); }
  33. BOOL CProcessCopy::DoCopy()
  34. {
  35. EnterCriticalSection(&m_CriticalSection);
  36. //Attach the clip board
  37. if(!m_oleData.AttachClipboard())
  38. EXIT_DO_COPY(FALSE);
  39. m_oleData.EnsureClipboardObject();
  40. //Included in copy if the data is supposed to be private
  41. //If it is there then return
  42. if(m_oleData.IsDataAvailable(RegisterClipboardFormat("Clipboard Viewer Ignore")))
  43. {
  44. EXIT_DO_COPY(FALSE);
  45. }
  46. if((theApp.m_bReloadTypes) || (m_SupportedTypes.GetSize() == 0))
  47. LoadSupportedTypes();
  48. //Start the copy process
  49. //This checks if valid data is available
  50. //If so it adds the text the the main table and returns the id
  51. long lID = StartCopyProcess();
  52. if(lID == -1)
  53. {
  54. EXIT_DO_COPY(FALSE);
  55. }
  56. try
  57. {
  58. //open the data table and add the data for supported types
  59. CDataTable recset;
  60. CString csDbString;
  61. recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Data" ,NULL);
  62. CLIPFORMAT format;
  63. int nSize = m_SupportedTypes.GetSize();
  64. for(int i = 0; i < nSize; i++)
  65. {
  66. format = m_SupportedTypes[i];
  67. if(m_oleData.IsDataAvailable(format))
  68. {
  69. recset.AddNew();
  70. recset.m_lParentID = lID;
  71. recset.m_strClipBoardFormat = GetFormatName(format);
  72. HGLOBAL hgData = m_oleData.GetGlobalData(format);
  73. bool bReadData = false;
  74. if(hgData != NULL)
  75. {
  76. recset.SetData(hgData);
  77. //update the DB
  78. recset.Update();
  79. bReadData = true;
  80. // Free the memory that GetGlobalData() allocated for us.
  81. GlobalUnlock(hgData);
  82. GlobalFree(hgData);
  83. hgData = NULL;
  84. }
  85. else
  86. {
  87. // The data isn't in global memory, so try getting an IStream
  88. // interface to it.
  89. STGMEDIUM stg;
  90. if(m_oleData.GetData(format, &stg))
  91. {
  92. switch(stg.tymed)
  93. {
  94. case TYMED_HGLOBAL:
  95. {
  96. recset.SetData(stg.hGlobal);
  97. //Update the db
  98. recset.Update();
  99. bReadData = true;
  100. }
  101. break;
  102. case TYMED_ISTREAM:
  103. {
  104. UINT uDataSize;
  105. LARGE_INTEGER li;
  106. ULARGE_INTEGER uli;
  107. li.HighPart = li.LowPart = 0;
  108. if ( SUCCEEDED( stg.pstm->Seek ( li, STREAM_SEEK_END, &uli )))
  109. {
  110. HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, uli.LowPart );
  111. void* pv = GlobalLock(hg);
  112. stg.pstm->Seek(li, STREAM_SEEK_SET, NULL);
  113. if(SUCCEEDED(stg.pstm->Read(pv, uli.LowPart, (PULONG)&uDataSize)))
  114. {
  115. GlobalUnlock(hg);
  116. recset.SetData(hg);
  117. //Update the DB
  118. recset.Update();
  119. bReadData = true;
  120. // Free the memory we just allocated.
  121. GlobalFree(hg);
  122. }
  123. else
  124. {
  125. GlobalUnlock(hg);
  126. }
  127. }
  128. }
  129. break; // case TYMED_ISTREAM
  130. }
  131. ReleaseStgMedium(&stg);
  132. }
  133. }
  134. if(bReadData)
  135. {
  136. GlobalUnlock(recset.m_ooData.m_hData);
  137. GlobalFree(recset.m_ooData.m_hData);
  138. recset.m_ooData.m_hData = NULL;
  139. }
  140. }
  141. }
  142. recset.Close();
  143. RemoveOldEntries();
  144. CGetSetOptions::SetTripCopyCount(-1);
  145. CGetSetOptions::SetTotalCopyCount(-1);
  146. }
  147. catch(CDaoException* e)
  148. {
  149. ASSERT(FALSE);
  150. e->Delete();
  151. }
  152. EXIT_DO_COPY(TRUE);
  153. }
  154. long CProcessCopy::StartCopyProcess()
  155. {
  156. CString csDescription;
  157. BOOL bReturn = FALSE;
  158. CLIPFORMAT MainType;
  159. long lReturnID = -1;
  160. if(!GetCopyInfo(MainType))
  161. return -1;
  162. if(!GetDescriptionText(csDescription))
  163. return -1;
  164. long lRecID;
  165. if((lRecID = DoesCopyEntryExist()) >= 0)
  166. {
  167. CMainTable recset;
  168. recset.Open("SELECT * FROM Main WHERE lID = %d", lRecID);
  169. if(!recset.IsEOF())
  170. {
  171. recset.Edit();
  172. //Set the time to now since the entry was allready in the db
  173. CTime now = CTime::GetCurrentTime();
  174. recset.m_lDate = (long)now.GetTime();
  175. recset.Update();
  176. ShowCopyProperties(lRecID);
  177. return -1;
  178. }
  179. else
  180. ASSERT(FALSE);
  181. }
  182. try
  183. {
  184. //There were valid types present add the text to the main table
  185. CMainTable recset;
  186. recset.Open("SELECT * FROM Main");
  187. recset.AddNew();
  188. CTime now = CTime::GetCurrentTime();
  189. recset.m_lDate = (long)now.GetTime();
  190. recset.m_strType = GetDescriptionString(MainType);
  191. recset.m_strText = csDescription;
  192. recset.m_lTotalCopySize = m_lTotalCopySize;
  193. recset.Update();
  194. recset.MoveLast();
  195. lReturnID = recset.m_lID;
  196. recset.Close();
  197. ShowCopyProperties(lReturnID);
  198. }
  199. catch(CDaoException* e)
  200. {
  201. ASSERT(FALSE);
  202. e->Delete();
  203. return -1;
  204. }
  205. return lReturnID;
  206. return -1;
  207. }
  208. void CProcessCopy::ShowCopyProperties(long lRecID)
  209. {
  210. if(theApp.ShowCopyProperties)
  211. {
  212. HWND hWndFocus = GetActiveWnd();
  213. ::SendMessage(theApp.m_MainhWnd, WM_COPYPROPERTIES, lRecID, 0);
  214. theApp.ShowCopyProperties = false;
  215. ::SetForegroundWindow(hWndFocus);
  216. }
  217. }
  218. BOOL CProcessCopy::GetCopyInfo(CLIPFORMAT &MainType)
  219. {
  220. m_lTotalCopySize = 0;
  221. MainType = 0;
  222. m_lSupportedTypesAvailable = 0;
  223. //For each type we want to save
  224. for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
  225. {
  226. //Is data available for that type
  227. if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
  228. {
  229. m_lSupportedTypesAvailable++;
  230. HGLOBAL hgData = m_oleData.GetGlobalData(m_SupportedTypes[i]);
  231. //Get the size of the data
  232. if(hgData != NULL)
  233. m_lTotalCopySize += GlobalSize(hgData);
  234. if(MainType == 0)
  235. MainType = m_SupportedTypes[i];
  236. }
  237. }
  238. return(m_lTotalCopySize > 0);
  239. }
  240. BOOL CProcessCopy::GetDescriptionText(CString &csText)
  241. {
  242. BOOL bRet = FALSE;
  243. if(m_oleData.IsDataAvailable(CF_TEXT))
  244. {
  245. //Get the text version of the data and return the text
  246. char *text;
  247. HGLOBAL hgData = m_oleData.GetGlobalData(CF_TEXT);
  248. if(hgData != NULL)
  249. {
  250. //Get the text from the clipboard
  251. text = (char *)GlobalLock(hgData);
  252. ULONG ulBufLen = GlobalSize(hgData);
  253. if(ulBufLen > LENGTH_OF_TEXT_SNIPET)
  254. ulBufLen = LENGTH_OF_TEXT_SNIPET;
  255. if( ulBufLen > 0 )
  256. {
  257. char* buf = csText.GetBuffer(ulBufLen);
  258. memcpy(buf, text, ulBufLen); // in most cases, last char == null
  259. buf[ulBufLen-1] = '\0'; // just in case not null terminated
  260. csText.ReleaseBuffer(); // scans for the null
  261. }
  262. //Unlock the data
  263. GlobalUnlock(hgData);
  264. // Free the memory that GetGlobalData() allocated for us.
  265. GlobalFree(hgData);
  266. bRet = TRUE;
  267. }
  268. }
  269. else
  270. {
  271. //If the text is not available then get the description
  272. for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
  273. {
  274. if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
  275. {
  276. csText = GetDescriptionString(m_SupportedTypes[i]);
  277. bRet = TRUE;
  278. break;
  279. }
  280. }
  281. }
  282. return bRet;
  283. }
  284. BOOL CProcessCopy::DoesCopyEntryExist()
  285. {
  286. try
  287. {
  288. //Look for any other entries that have the save size
  289. CMainTable recset;
  290. recset.Open("SELECT * FROM Main WHERE lTotalCopySize = %d", m_lTotalCopySize);
  291. while(!recset.IsEOF())
  292. {
  293. //if there is any then look if it is an exact match
  294. if(IsExactMatch(recset.m_lID))
  295. return recset.m_lID;
  296. recset.MoveNext();
  297. }
  298. recset.Close();
  299. }
  300. catch(CDaoException* e)
  301. {
  302. ASSERT(FALSE);
  303. e->Delete();
  304. }
  305. return -1;
  306. }
  307. BOOL CProcessCopy::IsExactMatch(long lParentID)
  308. {
  309. CDataTable recset;
  310. //First check if they both have the same number of saved types
  311. recset.Open("SELECT * FROM Data WHERE lParentID = %d", lParentID);
  312. recset.MoveLast();
  313. if(recset.GetRecordCount() != m_lSupportedTypesAvailable)
  314. return FALSE;
  315. recset.Close();
  316. //For each supported type
  317. for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
  318. {
  319. //That data is a available
  320. if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
  321. {
  322. //look if there is a data with the same clipboard format name 'CF_TEXT' 'CF_DIB'
  323. recset.Open("SELECT * FROM Data WHERE lParentID = %d AND strClipBoardFormat = \'%s\'",
  324. lParentID, GetFormatName(m_SupportedTypes[i]));
  325. //Move last to get the total returned
  326. recset.MoveLast();
  327. long lRecordCount = recset.GetRecordCount();
  328. //If it found one - it should only find one
  329. if(lRecordCount == 1)
  330. {
  331. //Check the internal data of each if it is not a match then return FALSE
  332. if(!recset.DataEqual(m_oleData.GetGlobalData(m_SupportedTypes[i])))
  333. return FALSE;
  334. }
  335. else if(lRecordCount == 0)
  336. return FALSE;
  337. else if(lRecordCount > 1)
  338. {
  339. ASSERT(FALSE);
  340. return FALSE;
  341. }
  342. recset.Close();
  343. }
  344. }
  345. return TRUE;
  346. }
  347. CString CProcessCopy::GetDescriptionString(CLIPFORMAT cbType)
  348. {
  349. switch(cbType)
  350. {
  351. case CF_TEXT:
  352. return "CF_TEXT";
  353. case CF_BITMAP:
  354. return "CF_BITMAP";
  355. case CF_METAFILEPICT:
  356. return "CF_METAFILEPICT";
  357. case CF_SYLK:
  358. return "CF_SYLK";
  359. case CF_DIF:
  360. return "CF_DIF";
  361. case CF_TIFF:
  362. return "CF_TIFF";
  363. case CF_OEMTEXT:
  364. return "CF_OEMTEXT";
  365. case CF_DIB:
  366. return "CF_DIB";
  367. case CF_PALETTE:
  368. return "CF_PALETTE";
  369. case CF_PENDATA:
  370. return "CF_PENDATA";
  371. case CF_RIFF:
  372. return "CF_RIFF";
  373. case CF_WAVE:
  374. return "CF_WAVE";
  375. case CF_UNICODETEXT:
  376. return "CF_UNICODETEXT";
  377. case CF_ENHMETAFILE:
  378. return "CF_ENHMETAFILE";
  379. case CF_HDROP:
  380. return "CF_HDROP";
  381. case CF_LOCALE:
  382. return "CF_LOCALE";
  383. case CF_OWNERDISPLAY:
  384. return "CF_OWNERDISPLAY";
  385. case CF_DSPTEXT:
  386. return "CF_DSPTEXT";
  387. case CF_DSPBITMAP:
  388. return "CF_DSPBITMAP";
  389. case CF_DSPMETAFILEPICT:
  390. return "CF_DSPMETAFILEPICT";
  391. case CF_DSPENHMETAFILE:
  392. return "CF_DSPENHMETAFILE";
  393. default:
  394. {
  395. //Not a default type get the name from the clipboard
  396. if (cbType != 0)
  397. {
  398. TCHAR szFormat[256];
  399. GetClipboardFormatName(cbType, szFormat, 256);
  400. return szFormat;
  401. }
  402. break;
  403. }
  404. }
  405. return "ERROR";
  406. }
  407. BOOL CProcessCopy::LoadSupportedTypes()
  408. {
  409. m_SupportedTypes.RemoveAll();
  410. try
  411. {
  412. CTypesTable recset;
  413. recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Types" ,NULL);
  414. if(recset.IsEOF())
  415. {
  416. m_SupportedTypes.Add(CF_TEXT);
  417. m_SupportedTypes.Add(RegisterClipboardFormat(CF_RTF));
  418. }
  419. while(!recset.IsEOF())
  420. {
  421. m_SupportedTypes.Add(GetFormatID(recset.m_TypeText));
  422. recset.MoveNext();
  423. }
  424. }
  425. catch(CDaoException* e)
  426. {
  427. ASSERT(FALSE);
  428. e->Delete();
  429. m_SupportedTypes.Add(CF_TEXT);
  430. m_SupportedTypes.Add(RegisterClipboardFormat(CF_RTF));
  431. }
  432. theApp.m_bReloadTypes = false;
  433. return TRUE;
  434. }