ProcessCopy.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. char* buf = csText.GetBuffer(ulBufLen);
  256. memcpy(buf, text, ulBufLen);
  257. buf[ulBufLen-1] = '\0';
  258. csText.ReleaseBuffer();
  259. //Unlock the data
  260. GlobalUnlock(hgData);
  261. // Free the memory that GetGlobalData() allocated for us.
  262. GlobalFree(hgData);
  263. bRet = TRUE;
  264. }
  265. }
  266. else
  267. {
  268. //If the text is not available then get the description
  269. for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
  270. {
  271. if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
  272. {
  273. csText = GetDescriptionString(m_SupportedTypes[i]);
  274. bRet = TRUE;
  275. break;
  276. }
  277. }
  278. }
  279. return bRet;
  280. }
  281. BOOL CProcessCopy::DoesCopyEntryExist()
  282. {
  283. try
  284. {
  285. //Look for any other entries that have the save size
  286. CMainTable recset;
  287. recset.Open("SELECT * FROM Main WHERE lTotalCopySize = %d", m_lTotalCopySize);
  288. while(!recset.IsEOF())
  289. {
  290. //if there is any then look if it is an exact match
  291. if(IsExactMatch(recset.m_lID))
  292. return recset.m_lID;
  293. recset.MoveNext();
  294. }
  295. recset.Close();
  296. }
  297. catch(CDaoException* e)
  298. {
  299. ASSERT(FALSE);
  300. e->Delete();
  301. }
  302. return -1;
  303. }
  304. BOOL CProcessCopy::IsExactMatch(long lParentID)
  305. {
  306. CDataTable recset;
  307. //First check if they both have the same number of saved types
  308. recset.Open("SELECT * FROM Data WHERE lParentID = %d", lParentID);
  309. recset.MoveLast();
  310. if(recset.GetRecordCount() != m_lSupportedTypesAvailable)
  311. return FALSE;
  312. recset.Close();
  313. //For each supported type
  314. for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
  315. {
  316. //That data is a available
  317. if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
  318. {
  319. //look if there is a data with the same clipboard format name 'CF_TEXT' 'CF_DIB'
  320. recset.Open("SELECT * FROM Data WHERE lParentID = %d AND strClipBoardFormat = \'%s\'",
  321. lParentID, GetFormatName(m_SupportedTypes[i]));
  322. //Move last to get the total returned
  323. recset.MoveLast();
  324. long lRecordCount = recset.GetRecordCount();
  325. //If it found one - it should only find one
  326. if(lRecordCount == 1)
  327. {
  328. //Check the internal data of each if it is not a match then return FALSE
  329. if(!recset.DataEqual(m_oleData.GetGlobalData(m_SupportedTypes[i])))
  330. return FALSE;
  331. }
  332. else if(lRecordCount == 0)
  333. return FALSE;
  334. else if(lRecordCount > 1)
  335. {
  336. ASSERT(FALSE);
  337. return FALSE;
  338. }
  339. recset.Close();
  340. }
  341. }
  342. return TRUE;
  343. }
  344. CString CProcessCopy::GetDescriptionString(CLIPFORMAT cbType)
  345. {
  346. switch(cbType)
  347. {
  348. case CF_TEXT:
  349. return "CF_TEXT";
  350. case CF_BITMAP:
  351. return "CF_BITMAP";
  352. case CF_METAFILEPICT:
  353. return "CF_METAFILEPICT";
  354. case CF_SYLK:
  355. return "CF_SYLK";
  356. case CF_DIF:
  357. return "CF_DIF";
  358. case CF_TIFF:
  359. return "CF_TIFF";
  360. case CF_OEMTEXT:
  361. return "CF_OEMTEXT";
  362. case CF_DIB:
  363. return "CF_DIB";
  364. case CF_PALETTE:
  365. return "CF_PALETTE";
  366. case CF_PENDATA:
  367. return "CF_PENDATA";
  368. case CF_RIFF:
  369. return "CF_RIFF";
  370. case CF_WAVE:
  371. return "CF_WAVE";
  372. case CF_UNICODETEXT:
  373. return "CF_UNICODETEXT";
  374. case CF_ENHMETAFILE:
  375. return "CF_ENHMETAFILE";
  376. case CF_HDROP:
  377. return "CF_HDROP";
  378. case CF_LOCALE:
  379. return "CF_LOCALE";
  380. case CF_OWNERDISPLAY:
  381. return "CF_OWNERDISPLAY";
  382. case CF_DSPTEXT:
  383. return "CF_DSPTEXT";
  384. case CF_DSPBITMAP:
  385. return "CF_DSPBITMAP";
  386. case CF_DSPMETAFILEPICT:
  387. return "CF_DSPMETAFILEPICT";
  388. case CF_DSPENHMETAFILE:
  389. return "CF_DSPENHMETAFILE";
  390. default:
  391. {
  392. //Not a default type get the name from the clipboard
  393. if (cbType != 0)
  394. {
  395. TCHAR szFormat[256];
  396. GetClipboardFormatName(cbType, szFormat, 256);
  397. return szFormat;
  398. }
  399. break;
  400. }
  401. }
  402. return "ERROR";
  403. }
  404. BOOL CProcessCopy::LoadSupportedTypes()
  405. {
  406. m_SupportedTypes.RemoveAll();
  407. try
  408. {
  409. CTypesTable recset;
  410. recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Types" ,NULL);
  411. if(recset.IsEOF())
  412. {
  413. m_SupportedTypes.Add(CF_TEXT);
  414. m_SupportedTypes.Add(RegisterClipboardFormat(CF_RTF));
  415. }
  416. while(!recset.IsEOF())
  417. {
  418. m_SupportedTypes.Add(GetFormatID(recset.m_TypeText));
  419. recset.MoveNext();
  420. }
  421. }
  422. catch(CDaoException* e)
  423. {
  424. ASSERT(FALSE);
  425. e->Delete();
  426. m_SupportedTypes.Add(CF_TEXT);
  427. m_SupportedTypes.Add(RegisterClipboardFormat(CF_RTF));
  428. }
  429. theApp.m_bReloadTypes = false;
  430. return TRUE;
  431. }