OleClipSource.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. #include "stdafx.h"
  2. #include "CP_Main.h"
  3. #include "OleClipSource.h"
  4. #include "shared/TextConvert.h"
  5. #include "CF_HDropAggregator.h"
  6. #include "CF_UnicodeTextAggregator.h"
  7. #include "CF_TextAggregator.h"
  8. #include "richtextaggregator.h"
  9. #include "htmlformataggregator.h"
  10. /*------------------------------------------------------------------*\
  11. COleClipSource
  12. \*------------------------------------------------------------------*/
  13. //IMPLEMENT_DYNAMIC(COleClipSource, COleDataSource)
  14. COleClipSource::COleClipSource()
  15. {
  16. m_bLoadedFormats = false;
  17. }
  18. COleClipSource::~COleClipSource()
  19. {
  20. }
  21. BOOL COleClipSource::DoDelayRender()
  22. {
  23. CClipTypes types;
  24. m_ClipIDs.GetTypes(types);
  25. INT_PTR count = types.GetSize();
  26. for(int i=0; i < count; i++)
  27. {
  28. DelayRenderData(types[i]);
  29. }
  30. return count > 0;
  31. }
  32. #include "Client.h"
  33. BOOL COleClipSource::DoImmediateRender()
  34. {
  35. if(m_bLoadedFormats)
  36. return TRUE;
  37. m_bLoadedFormats = true;
  38. if(m_pasteOptions.m_pPasteFormats != NULL)
  39. {
  40. return PutFormatOnClipboard(m_pasteOptions.m_pPasteFormats) > 0;
  41. }
  42. INT_PTR count = m_ClipIDs.GetSize();
  43. if(count <= 0)
  44. return 0;
  45. CClip clip;
  46. if(count > 1)
  47. {
  48. CStringA SepA = CTextConvert::ConvertToChar(g_Opt.GetMultiPasteSeparator());
  49. CCF_TextAggregator CFText(SepA);
  50. if(m_ClipIDs.AggregateData(CFText, CF_TEXT, g_Opt.m_bMultiPasteReverse))
  51. {
  52. CClipFormat cf(CF_TEXT, CFText.GetHGlobal());
  53. clip.m_Formats.Add(cf);
  54. //clip.m_Formats now owns the global data
  55. cf.m_autoDeleteData = false;
  56. }
  57. CStringW SepW = CTextConvert::ConvertToUnicode(g_Opt.GetMultiPasteSeparator());
  58. CCF_UnicodeTextAggregator CFUnicodeText(SepW);
  59. if(m_ClipIDs.AggregateData(CFUnicodeText, CF_UNICODETEXT, g_Opt.m_bMultiPasteReverse))
  60. {
  61. CClipFormat cf(CF_UNICODETEXT, CFUnicodeText.GetHGlobal());
  62. clip.m_Formats.Add(cf);
  63. //clip.m_Formats now owns the global data
  64. cf.m_autoDeleteData = false;
  65. }
  66. if ((m_pasteOptions.LimitFormatsToText()) &&
  67. clip.m_Formats.GetCount() == 0)
  68. {
  69. CCF_HDropAggregator HDrop;
  70. if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
  71. {
  72. CClipFormat cf(CF_UNICODETEXT, HDrop.GetHGlobalAsString());
  73. clip.m_Formats.Add(cf);
  74. //clip.m_Formats now owns the global data
  75. cf.m_autoDeleteData = false;
  76. }
  77. }
  78. else if (m_pasteOptions.LimitFormatsToText() == false)
  79. {
  80. CCF_HDropAggregator HDrop;
  81. if(m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
  82. {
  83. CClipFormat cf(CF_HDROP, HDrop.GetHGlobal());
  84. clip.m_Formats.Add(cf);
  85. //clip.m_Formats now owns the global data
  86. cf.m_autoDeleteData = false;
  87. }
  88. CRichTextAggregator RichText(SepA);
  89. if(m_ClipIDs.AggregateData(RichText, theApp.m_RTFFormat, g_Opt.m_bMultiPasteReverse))
  90. {
  91. CClipFormat cf(theApp.m_RTFFormat, RichText.GetHGlobal());
  92. clip.m_Formats.Add(cf);
  93. //clip.m_Formats now owns the global data
  94. cf.m_autoDeleteData = false;
  95. }
  96. CHTMLFormatAggregator Html(SepA);
  97. if(m_ClipIDs.AggregateData(Html, theApp.m_HTML_Format, g_Opt.m_bMultiPasteReverse))
  98. {
  99. CClipFormat cf(theApp.m_HTML_Format, Html.GetHGlobal());
  100. clip.m_Formats.Add(cf);
  101. //clip.m_Formats now owns the global data
  102. cf.m_autoDeleteData = false;
  103. }
  104. }
  105. }
  106. if (count >= 1 && clip.m_Formats.GetCount() == 0)
  107. {
  108. clip.LoadFormats(m_ClipIDs[0], m_pasteOptions.LimitFormatsToText());
  109. }
  110. if (m_pasteOptions.LimitFormatsToText())
  111. {
  112. PlainTextFilter(clip);
  113. }
  114. if(m_pasteOptions.m_pasteUpperCase ||
  115. m_pasteOptions.m_pasteLowerCase)
  116. {
  117. DoUpperLowerCase(clip, m_pasteOptions.m_pasteUpperCase);
  118. }
  119. else if(m_pasteOptions.m_pasteCapitalize)
  120. {
  121. Capitalize(clip);
  122. }
  123. else if(m_pasteOptions.m_pasteSentenceCase)
  124. {
  125. SentenceCase(clip);
  126. }
  127. return PutFormatOnClipboard(&clip.m_Formats) > 0;
  128. }
  129. void COleClipSource::DoUpperLowerCase(CClip &clip, bool upper)
  130. {
  131. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  132. if (unicodeTextFormat != NULL)
  133. {
  134. HGLOBAL data = unicodeTextFormat->Data();
  135. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  136. int size = (int) GlobalSize(data);
  137. CString cs(stringData, (size / sizeof(wchar_t)));
  138. GlobalUnlock(data);
  139. //free the old text we are going to replace it below with an upper case version
  140. unicodeTextFormat->Free();
  141. CString val;
  142. if (upper)
  143. {
  144. val = cs.MakeUpper();
  145. }
  146. else
  147. {
  148. val = cs.MakeLower();
  149. }
  150. long lLen = val.GetLength();
  151. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((lLen+1) * sizeof(wchar_t)));
  152. val.ReleaseBuffer();
  153. unicodeTextFormat->Data(hGlobal);
  154. }
  155. IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
  156. if (asciiTextFormat != NULL)
  157. {
  158. HGLOBAL data = asciiTextFormat->Data();
  159. char * stringData = (char *) GlobalLock(data);
  160. int size = (int) GlobalSize(data);
  161. CStringA cs(stringData, size);
  162. GlobalUnlock(data);
  163. //free the old text we are going to replace it below with an upper case version
  164. asciiTextFormat->Free();
  165. CString val;
  166. if (upper)
  167. {
  168. val = cs.MakeUpper();
  169. }
  170. else
  171. {
  172. val = cs.MakeLower();
  173. }
  174. long lLen = val.GetLength();
  175. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(lLen), lLen + sizeof(char));
  176. val.ReleaseBuffer();
  177. asciiTextFormat->Data(hGlobal);
  178. }
  179. }
  180. void COleClipSource::Capitalize(CClip &clip)
  181. {
  182. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  183. if (unicodeTextFormat != NULL)
  184. {
  185. HGLOBAL data = unicodeTextFormat->Data();
  186. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  187. int size = (int) GlobalSize(data);
  188. CString cs(stringData, (size / sizeof(wchar_t)));
  189. GlobalUnlock(data);
  190. //free the old text we are going to replace it below with an upper case version
  191. unicodeTextFormat->Free();
  192. CString val = cs.MakeLower();
  193. long len = val.GetLength();
  194. if (len > 0)
  195. {
  196. wchar_t * pText = val.GetBuffer();
  197. pText[0] = toupper(pText[0]);
  198. bool capitalize = false;
  199. for (int i = 1; i < len; i++)
  200. {
  201. wchar_t item = pText[i];
  202. if (item == ' ')
  203. {
  204. capitalize = true;
  205. }
  206. else if (capitalize)
  207. {
  208. pText[i] = toupper(item);
  209. capitalize = false;
  210. }
  211. }
  212. }
  213. val.ReleaseBuffer();
  214. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
  215. unicodeTextFormat->Data(hGlobal);
  216. }
  217. //test
  218. IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
  219. if (asciiTextFormat != NULL)
  220. {
  221. HGLOBAL data = asciiTextFormat->Data();
  222. char * stringData = (char *) GlobalLock(data);
  223. int size = (int) GlobalSize(data);
  224. CStringA cs(stringData, size);
  225. GlobalUnlock(data);
  226. //free the old text we are going to replace it below with an upper case version
  227. asciiTextFormat->Free();
  228. CStringA val = cs.MakeLower();
  229. long len = val.GetLength();
  230. if (len > 0)
  231. {
  232. char * pText = val.GetBuffer();
  233. pText[0] = toupper(pText[0]);
  234. bool capitalize = false;
  235. for (int i = 1; i < len; i++)
  236. {
  237. wchar_t item = pText[i];
  238. if (item == ' ')
  239. {
  240. capitalize = true;
  241. }
  242. else if (capitalize)
  243. {
  244. pText[i] = toupper(item);
  245. capitalize = false;
  246. }
  247. }
  248. }
  249. val.ReleaseBuffer();
  250. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), (len + 1));
  251. asciiTextFormat->Data(hGlobal);
  252. }
  253. }
  254. void COleClipSource::SentenceCase(CClip &clip)
  255. {
  256. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  257. if (unicodeTextFormat != NULL)
  258. {
  259. HGLOBAL data = unicodeTextFormat->Data();
  260. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  261. int size = (int) GlobalSize(data);
  262. CString cs(stringData, (size / sizeof(wchar_t)));
  263. GlobalUnlock(data);
  264. //free the old text we are going to replace it below with an upper case version
  265. unicodeTextFormat->Free();
  266. CString val = cs.MakeLower();
  267. long len = val.GetLength();
  268. if (len > 0)
  269. {
  270. wchar_t * pText = val.GetBuffer();
  271. pText[0] = toupper(pText[0]);
  272. bool capitalize = false;
  273. for (int i = 1; i < len; i++)
  274. {
  275. wchar_t item = pText[i];
  276. if (item == '.' ||
  277. item == '!' ||
  278. item == '?')
  279. {
  280. capitalize = true;
  281. }
  282. else if (capitalize && item != ' ')
  283. {
  284. pText[i] = toupper(item);
  285. capitalize = false;
  286. }
  287. }
  288. }
  289. val.ReleaseBuffer();
  290. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
  291. unicodeTextFormat->Data(hGlobal);
  292. }
  293. IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
  294. if (asciiTextFormat != NULL)
  295. {
  296. HGLOBAL data = asciiTextFormat->Data();
  297. char * stringData = (char *) GlobalLock(data);
  298. int size = (int) GlobalSize(data);
  299. CStringA cs(stringData, size);
  300. GlobalUnlock(data);
  301. //free the old text we are going to replace it below with an upper case version
  302. asciiTextFormat->Free();
  303. CStringA val = cs.MakeLower();
  304. long len = val.GetLength();
  305. if (len > 0)
  306. {
  307. char * pText = val.GetBuffer();
  308. pText[0] = toupper(pText[0]);
  309. bool capitalize = false;
  310. for (int i = 1; i < len; i++)
  311. {
  312. wchar_t item = pText[i];
  313. if (item == '.' ||
  314. item == '!' ||
  315. item == '?')
  316. {
  317. capitalize = true;
  318. }
  319. else if (capitalize && item != ' ')
  320. {
  321. pText[i] = toupper(item);
  322. capitalize = false;
  323. }
  324. }
  325. }
  326. val.ReleaseBuffer();
  327. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), (len + 1));
  328. asciiTextFormat->Data(hGlobal);
  329. }
  330. }
  331. void COleClipSource::PlainTextFilter(CClip &clip)
  332. {
  333. bool foundText = false;
  334. INT_PTR hDropIndex = -1;
  335. INT_PTR count = clip.m_Formats.GetCount();
  336. for (INT_PTR i = 0; i < count; i++)
  337. {
  338. CClipFormat *pCF = &clip.m_Formats.ElementAt(i);
  339. if (pCF->m_cfType == CF_TEXT ||
  340. pCF->m_cfType == CF_UNICODETEXT)
  341. {
  342. foundText = true;
  343. }
  344. else if (pCF->m_cfType == CF_HDROP)
  345. {
  346. hDropIndex = i;
  347. }
  348. }
  349. if (foundText &&
  350. hDropIndex > -1)
  351. {
  352. clip.m_Formats.RemoveAt(hDropIndex);
  353. }
  354. else if (foundText == false &&
  355. hDropIndex > -1)
  356. {
  357. CCF_HDropAggregator HDrop;
  358. if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
  359. {
  360. clip.m_Formats.Add(CClipFormat(CF_UNICODETEXT, HDrop.GetHGlobalAsString()));
  361. }
  362. }
  363. }
  364. INT_PTR COleClipSource::PutFormatOnClipboard(CClipFormats *pFormats)
  365. {
  366. Log(_T("Start of put format on clipboard"));
  367. CClipFormat* pCF;
  368. INT_PTR count = pFormats->GetSize();
  369. bool bDelayedRenderCF_HDROP = false;
  370. INT_PTR i = 0;
  371. //see if the html format is in the list
  372. //if it is the list we will not paste CF_TEXT
  373. for(i = 0; i < count; i++)
  374. {
  375. pCF = &pFormats->ElementAt(i);
  376. if(pCF->m_cfType == theApp.m_RemoteCF_HDROP)
  377. {
  378. bDelayedRenderCF_HDROP = true;
  379. }
  380. }
  381. for(i = 0; i < count; i++)
  382. {
  383. pCF = &pFormats->ElementAt(i);
  384. if(bDelayedRenderCF_HDROP)
  385. {
  386. if(pCF->m_cfType == CF_HDROP)
  387. {
  388. LogSendRecieveInfo("Added delayed cf_hdrop to clipboard");
  389. DelayRenderData(pCF->m_cfType);
  390. }
  391. continue;
  392. }
  393. wchar_t * stringData = (wchar_t *) GlobalLock(pCF->m_hgData);
  394. int size = (int) GlobalSize(pCF->m_hgData);
  395. CString cs(stringData, (size / sizeof(wchar_t)));
  396. GlobalUnlock(pCF->m_hgData);
  397. Log(StrF(_T("Setting clipboard type: %s to the clipboard"), GetFormatName(pCF->m_cfType)));
  398. CacheGlobalData(pCF->m_cfType, pCF->m_hgData);
  399. pCF->m_hgData = 0; // OLE owns it now
  400. }
  401. pFormats->RemoveAll();
  402. m_bLoadedFormats = true;
  403. Log(_T("End of put format on clipboard"));
  404. return count;
  405. }
  406. BOOL COleClipSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  407. {
  408. static bool bInHere = false;
  409. if(bInHere)
  410. {
  411. return FALSE;
  412. }
  413. bInHere = true;
  414. HGLOBAL hData = NULL;
  415. CClipFormat *pFind = m_DelayRenderedFormats.FindFormat(lpFormatEtc->cfFormat);
  416. if(pFind)
  417. {
  418. if(pFind->m_hgData)
  419. {
  420. hData = NewGlobalH(pFind->m_hgData, GlobalSize(pFind->m_hgData));
  421. }
  422. }
  423. else
  424. {
  425. LogSendRecieveInfo("Delayed Render, getting data from remote machine");
  426. CClip clip;
  427. if(m_ClipIDs.GetCount() > 0)
  428. {
  429. clip.LoadFormats(m_ClipIDs[0]);
  430. CClipFormat *pDittoDelayCF_HDROP = clip.m_Formats.FindFormat(theApp.m_RemoteCF_HDROP);
  431. CClipFormat *pCF_HDROP = clip.m_Formats.FindFormat(CF_HDROP);
  432. if(pDittoDelayCF_HDROP && pCF_HDROP)
  433. {
  434. CDittoCF_HDROP *pData = (CDittoCF_HDROP*)GlobalLock(pDittoDelayCF_HDROP->m_hgData);
  435. if(pData)
  436. {
  437. CString csComputerName;
  438. CString csIP;
  439. CTextConvert::ConvertFromUTF8(pData->m_cIP, csIP);
  440. CTextConvert::ConvertFromUTF8(pData->m_cComputerName, csComputerName);
  441. GlobalUnlock(pDittoDelayCF_HDROP->m_hgData);
  442. CClient cl;
  443. hData = cl.RequestCopiedFiles(*pCF_HDROP, csIP, csComputerName);
  444. }
  445. }
  446. else
  447. {
  448. hData = m_ClipIDs.Render(lpFormatEtc->cfFormat);
  449. }
  450. }
  451. //Add to a cache of already rendered data
  452. //Windows seems to call this function multiple times
  453. //so only the first time do we need to go get the data
  454. HGLOBAL hCopy = NULL;
  455. if(hData)
  456. {
  457. hCopy = NewGlobalH(hData, GlobalSize(hData));
  458. }
  459. CClipFormat format(lpFormatEtc->cfFormat, hCopy);
  460. format.m_autoDeleteData = false; //owned by m_DelayRenderedFormats
  461. m_DelayRenderedFormats.Add(format);
  462. }
  463. BOOL bRet = FALSE;
  464. if(hData)
  465. {
  466. // if phGlobal is null, we can just give the allocated mem
  467. // else, our data must fit within the GlobalSize(*phGlobal)
  468. if(*phGlobal == 0)
  469. {
  470. *phGlobal = hData;
  471. }
  472. else
  473. {
  474. SIZE_T len = min(::GlobalSize(*phGlobal), ::GlobalSize(hData));
  475. if(len)
  476. {
  477. CopyToGlobalHH(*phGlobal, hData, len);
  478. }
  479. ::GlobalFree(hData);
  480. }
  481. bRet = TRUE;
  482. }
  483. bInHere = false;
  484. return bRet;
  485. }