OleClipSource.cpp 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  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. #include "Shared\Tokenizer.h"
  11. #include <random>
  12. #include "Client.h"
  13. #include "sqlite\unicode\unistr.h"
  14. #include "sqlite\unicode\uchar.h"
  15. #include "Path.h"
  16. #include "Md5.h"
  17. /*------------------------------------------------------------------*\
  18. COleClipSource
  19. \*------------------------------------------------------------------*/
  20. //IMPLEMENT_DYNAMIC(COleClipSource, COleDataSource)
  21. COleClipSource::COleClipSource()
  22. {
  23. m_bLoadedFormats = false;
  24. m_convertToHDROPOnDelayRender = false;
  25. }
  26. COleClipSource::~COleClipSource()
  27. {
  28. }
  29. BOOL COleClipSource::DoDelayRender()
  30. {
  31. CClipTypes types;
  32. m_ClipIDs.GetTypes(types);
  33. bool foundHDrop = false;
  34. INT_PTR count = types.GetSize();
  35. for(int i=0; i < count; i++)
  36. {
  37. if (m_pasteOptions.m_dragDropFilesOnly)
  38. {
  39. if (types[i] == CF_HDROP)
  40. {
  41. DelayRenderData(types[i]);
  42. }
  43. }
  44. else
  45. {
  46. DelayRenderData(types[i]);
  47. }
  48. if (types[i] == CF_HDROP)
  49. {
  50. foundHDrop = true;
  51. }
  52. }
  53. if (foundHDrop == false)
  54. {
  55. DelayRenderData(CF_HDROP);
  56. m_convertToHDROPOnDelayRender = true;
  57. }
  58. return count > 0;
  59. }
  60. BOOL COleClipSource::DoImmediateRender()
  61. {
  62. if(m_bLoadedFormats)
  63. return TRUE;
  64. m_bLoadedFormats = true;
  65. if(m_pasteOptions.m_pPasteFormats != NULL)
  66. {
  67. return PutFormatOnClipboard(m_pasteOptions.m_pPasteFormats) > 0;
  68. }
  69. INT_PTR count = m_ClipIDs.GetSize();
  70. if(count <= 0)
  71. return 0;
  72. CClip clip;
  73. if(count > 1)
  74. {
  75. CStringA SepA = CTextConvert::ConvertToChar(g_Opt.GetMultiPasteSeparator());
  76. CCF_TextAggregator CFText(SepA);
  77. if(m_ClipIDs.AggregateData(CFText, CF_TEXT, g_Opt.m_bMultiPasteReverse))
  78. {
  79. CClipFormat cf(CF_TEXT, CFText.GetHGlobal());
  80. clip.m_Formats.Add(cf);
  81. //clip.m_Formats now owns the global data
  82. cf.m_autoDeleteData = false;
  83. }
  84. CStringW SepW = CTextConvert::ConvertToUnicode(g_Opt.GetMultiPasteSeparator());
  85. CCF_UnicodeTextAggregator CFUnicodeText(SepW);
  86. if(m_ClipIDs.AggregateData(CFUnicodeText, CF_UNICODETEXT, g_Opt.m_bMultiPasteReverse))
  87. {
  88. CClipFormat cf(CF_UNICODETEXT, CFUnicodeText.GetHGlobal());
  89. clip.m_Formats.Add(cf);
  90. //clip.m_Formats now owns the global data
  91. cf.m_autoDeleteData = false;
  92. }
  93. if ((m_pasteOptions.LimitFormatsToText()) &&
  94. clip.m_Formats.GetCount() == 0)
  95. {
  96. CCF_HDropAggregator HDrop;
  97. if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
  98. {
  99. CClipFormat cf(CF_UNICODETEXT, HDrop.GetHGlobalAsString());
  100. clip.m_Formats.Add(cf);
  101. //clip.m_Formats now owns the global data
  102. cf.m_autoDeleteData = false;
  103. }
  104. }
  105. else if (m_pasteOptions.LimitFormatsToText() == false)
  106. {
  107. CCF_HDropAggregator HDrop;
  108. if(m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
  109. {
  110. CClipFormat cf(CF_HDROP, HDrop.GetHGlobal());
  111. clip.m_Formats.Add(cf);
  112. //clip.m_Formats now owns the global data
  113. cf.m_autoDeleteData = false;
  114. }
  115. CRichTextAggregator RichText(SepA);
  116. if(m_ClipIDs.AggregateData(RichText, theApp.m_RTFFormat, g_Opt.m_bMultiPasteReverse))
  117. {
  118. CClipFormat cf(theApp.m_RTFFormat, RichText.GetHGlobal());
  119. clip.m_Formats.Add(cf);
  120. //clip.m_Formats now owns the global data
  121. cf.m_autoDeleteData = false;
  122. }
  123. CHTMLFormatAggregator Html(SepA);
  124. if(m_ClipIDs.AggregateData(Html, theApp.m_HTML_Format, g_Opt.m_bMultiPasteReverse))
  125. {
  126. CClipFormat cf(theApp.m_HTML_Format, Html.GetHGlobal());
  127. clip.m_Formats.Add(cf);
  128. //clip.m_Formats now owns the global data
  129. cf.m_autoDeleteData = false;
  130. }
  131. }
  132. }
  133. if (count >= 1 && clip.m_Formats.GetCount() == 0)
  134. {
  135. clip.LoadFormats(m_ClipIDs[0], m_pasteOptions.LimitFormatsToText(), m_pasteOptions.IncludeRTFForTextOnly());
  136. }
  137. if (m_pasteOptions.LimitFormatsToText())
  138. {
  139. PlainTextFilter(clip);
  140. }
  141. if(m_pasteOptions.m_pasteUpperCase ||
  142. m_pasteOptions.m_pasteLowerCase)
  143. {
  144. DoUpperLowerCase(clip, m_pasteOptions.m_pasteUpperCase);
  145. }
  146. else if(m_pasteOptions.m_pasteCapitalize)
  147. {
  148. Capitalize(clip);
  149. }
  150. else if(m_pasteOptions.m_pasteSentenceCase)
  151. {
  152. SentenceCase(clip);
  153. }
  154. else if(m_pasteOptions.m_pasteRemoveLineFeeds)
  155. {
  156. RemoveLineFeeds(clip);
  157. }
  158. else if(m_pasteOptions.m_pasteAddOneLineFeed)
  159. {
  160. AddLineFeeds(clip, 1);
  161. }
  162. else if (m_pasteOptions.m_pasteAddTwoLineFeeds)
  163. {
  164. AddLineFeeds(clip, 2);
  165. }
  166. else if (m_pasteOptions.m_pasteTypoglycemia)
  167. {
  168. Typoglycemia(clip);
  169. }
  170. else if (m_pasteOptions.m_pasteAddingDateTime)
  171. {
  172. AddDateTime(clip);
  173. }
  174. SaveDittoFileDataToFile(clip);
  175. return PutFormatOnClipboard(&clip.m_Formats) > 0;
  176. }
  177. void COleClipSource::DoUpperLowerCase(CClip &clip, bool upper)
  178. {
  179. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  180. if (unicodeTextFormat != NULL)
  181. {
  182. HGLOBAL data = unicodeTextFormat->Data();
  183. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  184. int size = (int) GlobalSize(data);
  185. icu::UnicodeString s = stringData;
  186. GlobalUnlock(data);
  187. //free the old text we are going to replace it below with an upper case version
  188. unicodeTextFormat->Free();
  189. icu::UnicodeString val;
  190. if (upper)
  191. {
  192. val = s.toUpper();
  193. }
  194. else
  195. {
  196. val = s.toLower();
  197. }
  198. long lLen = val.length();
  199. HGLOBAL hGlobal = NewGlobalP((LPVOID)val.getTerminatedBuffer(), ((lLen+1) * sizeof(wchar_t)));
  200. val.releaseBuffer();
  201. unicodeTextFormat->Data(hGlobal);
  202. }
  203. IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
  204. if (asciiTextFormat != NULL)
  205. {
  206. HGLOBAL data = asciiTextFormat->Data();
  207. char * stringData = (char *) GlobalLock(data);
  208. int size = (int) GlobalSize(data);
  209. CStringA cs(stringData);
  210. GlobalUnlock(data);
  211. //free the old text we are going to replace it below with an upper case version
  212. asciiTextFormat->Free();
  213. CString val;
  214. if (upper)
  215. {
  216. val = cs.MakeUpper();
  217. }
  218. else
  219. {
  220. val = cs.MakeLower();
  221. }
  222. long lLen = val.GetLength();
  223. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(lLen), lLen + sizeof(char));
  224. val.ReleaseBuffer();
  225. asciiTextFormat->Data(hGlobal);
  226. }
  227. }
  228. void COleClipSource::Capitalize(CClip &clip)
  229. {
  230. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  231. if (unicodeTextFormat != NULL)
  232. {
  233. HGLOBAL data = unicodeTextFormat->Data();
  234. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  235. int size = (int) GlobalSize(data);
  236. CString cs(stringData);
  237. GlobalUnlock(data);
  238. //free the old text we are going to replace it below with an upper case version
  239. unicodeTextFormat->Free();
  240. icu::UnicodeString temp = cs;
  241. CString val = temp.toLower().getTerminatedBuffer();
  242. long len = val.GetLength();
  243. if (len > 0)
  244. {
  245. wchar_t * pText = val.GetBuffer();
  246. pText[0] = u_toupper(pText[0]);
  247. bool capitalize = false;
  248. for (int i = 1; i < len; i++)
  249. {
  250. wchar_t item = pText[i];
  251. if (item == ' ')
  252. {
  253. capitalize = true;
  254. }
  255. else if (capitalize)
  256. {
  257. pText[i] = u_toupper(item);
  258. capitalize = false;
  259. }
  260. }
  261. }
  262. val.ReleaseBuffer();
  263. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
  264. unicodeTextFormat->Data(hGlobal);
  265. }
  266. //my change
  267. //test
  268. //second test
  269. IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
  270. if (asciiTextFormat != NULL)
  271. {
  272. HGLOBAL data = asciiTextFormat->Data();
  273. char * stringData = (char *) GlobalLock(data);
  274. int size = (int) GlobalSize(data);
  275. CStringA cs(stringData);
  276. GlobalUnlock(data);
  277. //free the old text we are going to replace it below with an upper case version
  278. asciiTextFormat->Free();
  279. CStringA val = cs.MakeLower();
  280. long len = val.GetLength();
  281. if (len > 0)
  282. {
  283. char * pText = val.GetBuffer();
  284. pText[0] = toupper(pText[0]);
  285. bool capitalize = false;
  286. for (int i = 1; i < len; i++)
  287. {
  288. wchar_t item = pText[i];
  289. if (item == ' ')
  290. {
  291. capitalize = true;
  292. }
  293. else if (capitalize)
  294. {
  295. pText[i] = toupper(item);
  296. capitalize = false;
  297. }
  298. }
  299. }
  300. val.ReleaseBuffer();
  301. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), (len + 1));
  302. asciiTextFormat->Data(hGlobal);
  303. }
  304. }
  305. void COleClipSource::SentenceCase(CClip &clip)
  306. {
  307. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  308. if (unicodeTextFormat != NULL)
  309. {
  310. HGLOBAL data = unicodeTextFormat->Data();
  311. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  312. int size = (int) GlobalSize(data);
  313. CString cs(stringData);
  314. GlobalUnlock(data);
  315. //free the old text we are going to replace it below with an upper case version
  316. unicodeTextFormat->Free();
  317. icu::UnicodeString temp = cs;
  318. CString val = temp.toLower().getTerminatedBuffer();
  319. long len = val.GetLength();
  320. if (len > 0)
  321. {
  322. wchar_t * pText = val.GetBuffer();
  323. pText[0] = u_toupper(pText[0]);
  324. bool capitalize = false;
  325. for (int i = 1; i < len; i++)
  326. {
  327. wchar_t item = pText[i];
  328. if (item == '.' ||
  329. item == '!' ||
  330. item == '?')
  331. {
  332. capitalize = true;
  333. }
  334. else if (capitalize && item != ' ')
  335. {
  336. pText[i] = u_toupper(item);
  337. capitalize = false;
  338. }
  339. }
  340. }
  341. val.ReleaseBuffer();
  342. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
  343. unicodeTextFormat->Data(hGlobal);
  344. }
  345. IClipFormat *asciiTextFormat = clip.m_Formats.FindFormatEx(CF_TEXT);
  346. if (asciiTextFormat != NULL)
  347. {
  348. HGLOBAL data = asciiTextFormat->Data();
  349. char * stringData = (char *) GlobalLock(data);
  350. int size = (int) GlobalSize(data);
  351. CStringA cs(stringData);
  352. GlobalUnlock(data);
  353. //free the old text we are going to replace it below with an upper case version
  354. asciiTextFormat->Free();
  355. CStringA val = cs.MakeLower();
  356. long len = val.GetLength();
  357. if (len > 0)
  358. {
  359. char * pText = val.GetBuffer();
  360. pText[0] = toupper(pText[0]);
  361. bool capitalize = false;
  362. for (int i = 1; i < len; i++)
  363. {
  364. wchar_t item = pText[i];
  365. if (item == '.' ||
  366. item == '!' ||
  367. item == '?')
  368. {
  369. capitalize = true;
  370. }
  371. else if (capitalize && item != ' ')
  372. {
  373. pText[i] = toupper(item);
  374. capitalize = false;
  375. }
  376. }
  377. }
  378. val.ReleaseBuffer();
  379. HGLOBAL hGlobal = NewGlobalP(val.GetBuffer(), (len + 1));
  380. asciiTextFormat->Data(hGlobal);
  381. }
  382. }
  383. void COleClipSource::PlainTextFilter(CClip &clip)
  384. {
  385. bool foundText = false;
  386. INT_PTR hDropIndex = -1;
  387. INT_PTR count = clip.m_Formats.GetCount();
  388. for (INT_PTR i = 0; i < count; i++)
  389. {
  390. CClipFormat *pCF = &clip.m_Formats.ElementAt(i);
  391. if (pCF->m_cfType == CF_TEXT ||
  392. pCF->m_cfType == CF_UNICODETEXT)
  393. {
  394. foundText = true;
  395. }
  396. else if (pCF->m_cfType == CF_HDROP)
  397. {
  398. hDropIndex = i;
  399. }
  400. }
  401. if (foundText &&
  402. hDropIndex > -1)
  403. {
  404. clip.m_Formats.RemoveAt(hDropIndex);
  405. }
  406. else if (foundText == false &&
  407. hDropIndex > -1)
  408. {
  409. CCF_HDropAggregator HDrop;
  410. if (m_ClipIDs.AggregateData(HDrop, CF_HDROP, g_Opt.m_bMultiPasteReverse))
  411. {
  412. clip.m_Formats.RemoveAt(hDropIndex);
  413. CClipFormat format(CF_UNICODETEXT, HDrop.GetHGlobalAsString());
  414. clip.m_Formats.Add(format);
  415. format.m_autoDeleteData = false; //owned by m_DelayRenderedFormats
  416. }
  417. }
  418. }
  419. void COleClipSource::RemoveLineFeeds(CClip &clip)
  420. {
  421. IClipFormat *pUnicodeText = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  422. if (pUnicodeText != NULL)
  423. {
  424. wchar_t *stringData = (wchar_t *) GlobalLock(pUnicodeText->Data());
  425. if (stringData != NULL)
  426. {
  427. CStringW string(stringData);
  428. GlobalUnlock(pUnicodeText->Data());
  429. pUnicodeText->Free();
  430. int count = string.Replace(_T("\r\n"), _T(" "));
  431. count = string.Replace(_T("\r"), _T(" "));
  432. count = string.Replace(_T("\n"), _T(" "));
  433. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1) * sizeof(wchar_t)));
  434. pUnicodeText->Data(hGlobal);
  435. }
  436. }
  437. IClipFormat *pAsciiText = clip.m_Formats.FindFormatEx(CF_TEXT);
  438. if (pAsciiText != NULL)
  439. {
  440. char *stringData = (char *) GlobalLock(pAsciiText->Data());
  441. if (stringData != NULL)
  442. {
  443. CStringA string(stringData);
  444. GlobalUnlock(pAsciiText->Data());
  445. pAsciiText->Free();
  446. int count = string.Replace("\r\n", " ");
  447. count = string.Replace("\r", " ");
  448. count = string.Replace("\n", " ");
  449. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1)));
  450. pAsciiText->Data(hGlobal);
  451. }
  452. }
  453. IClipFormat *pRTFFormat = clip.m_Formats.FindFormatEx(theApp.m_RTFFormat);
  454. if (pRTFFormat != NULL)
  455. {
  456. char *stringData = (char *) GlobalLock(pRTFFormat->Data());
  457. if (stringData != NULL)
  458. {
  459. CStringA string(stringData);
  460. GlobalUnlock(pRTFFormat->Data());
  461. pRTFFormat->Free();
  462. int count = string.Replace("\\par\r\n", " ");
  463. int count2 = string.Replace("\\par ", " ");
  464. int count3 = string.Replace("\\line ", " ");
  465. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1)));
  466. pRTFFormat->Data(hGlobal);
  467. }
  468. }
  469. }
  470. void COleClipSource::AddLineFeeds(CClip &clip, int count)
  471. {
  472. IClipFormat *pUnicodeText = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  473. if (pUnicodeText != NULL)
  474. {
  475. wchar_t *stringData = (wchar_t *) GlobalLock(pUnicodeText->Data());
  476. if (stringData != NULL)
  477. {
  478. CStringW string(stringData);
  479. GlobalUnlock(pUnicodeText->Data());
  480. pUnicodeText->Free();
  481. for(int i = 0; i < count; i++)
  482. {
  483. string += _T("\r\n");
  484. }
  485. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1) * sizeof(wchar_t)));
  486. pUnicodeText->Data(hGlobal);
  487. }
  488. }
  489. IClipFormat *pAsciiText = clip.m_Formats.FindFormatEx(CF_TEXT);
  490. if (pAsciiText != NULL)
  491. {
  492. char *stringData = (char *) GlobalLock(pAsciiText->Data());
  493. if (stringData != NULL)
  494. {
  495. CStringA string(stringData);
  496. GlobalUnlock(pAsciiText->Data());
  497. pAsciiText->Free();
  498. for (int i = 0; i < count; i++)
  499. {
  500. string += _T("\r\n");
  501. }
  502. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1)));
  503. pAsciiText->Data(hGlobal);
  504. }
  505. }
  506. IClipFormat *pRTFFormat = clip.m_Formats.FindFormatEx(theApp.m_RTFFormat);
  507. if (pRTFFormat != NULL)
  508. {
  509. char *stringData = (char *) GlobalLock(pRTFFormat->Data());
  510. if (stringData != NULL)
  511. {
  512. CStringA string(stringData);
  513. GlobalUnlock(pRTFFormat->Data());
  514. pRTFFormat->Free();
  515. for (int i = 0; i < count; i++)
  516. {
  517. int pos = string.ReverseFind('}');
  518. if (pos >= 0)
  519. {
  520. int count = string.Insert(pos, "\\par\r\n");
  521. }
  522. }
  523. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1)));
  524. pRTFFormat->Data(hGlobal);
  525. }
  526. }
  527. }
  528. void COleClipSource::AddDateTime(CClip &clip)
  529. {
  530. IClipFormat *pUnicodeText = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  531. if (pUnicodeText != NULL)
  532. {
  533. wchar_t *stringData = (wchar_t *)GlobalLock(pUnicodeText->Data());
  534. if (stringData != NULL)
  535. {
  536. CStringW string(stringData);
  537. GlobalUnlock(pUnicodeText->Data());
  538. pUnicodeText->Free();
  539. string += _T("\r\n");
  540. COleDateTime now(COleDateTime::GetCurrentTime());
  541. string += now.Format();
  542. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1) * sizeof(wchar_t)));
  543. pUnicodeText->Data(hGlobal);
  544. }
  545. }
  546. IClipFormat *pAsciiText = clip.m_Formats.FindFormatEx(CF_TEXT);
  547. if (pAsciiText != NULL)
  548. {
  549. char *stringData = (char *)GlobalLock(pAsciiText->Data());
  550. if (stringData != NULL)
  551. {
  552. CStringA string(stringData);
  553. GlobalUnlock(pAsciiText->Data());
  554. pAsciiText->Free();
  555. string += "\r\n\r\n";
  556. COleDateTime now(COleDateTime::GetCurrentTime());
  557. string += CTextConvert::UnicodeStringToMultiByte(now.Format());
  558. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1)));
  559. pAsciiText->Data(hGlobal);
  560. }
  561. }
  562. IClipFormat *pRTFFormat = clip.m_Formats.FindFormatEx(theApp.m_RTFFormat);
  563. if (pRTFFormat != NULL)
  564. {
  565. char *stringData = (char *)GlobalLock(pRTFFormat->Data());
  566. if (stringData != NULL)
  567. {
  568. CStringA string(stringData);
  569. GlobalUnlock(pRTFFormat->Data());
  570. pRTFFormat->Free();
  571. int pos = string.ReverseFind('}');
  572. if (pos >= 0)
  573. {
  574. string += _T("\r\n\r\n");
  575. COleDateTime now(COleDateTime::GetCurrentTime());
  576. CStringA insert;
  577. insert.Format("\\par\r\n\\par\r\n%s", CTextConvert::UnicodeStringToMultiByte(now.Format()));
  578. int count = string.Insert(pos, insert);
  579. }
  580. HGLOBAL hGlobal = NewGlobalP(string.GetBuffer(), ((string.GetLength() + 1)));
  581. pRTFFormat->Data(hGlobal);
  582. }
  583. }
  584. }
  585. void COleClipSource::SaveDittoFileDataToFile(CClip &clip)
  586. {
  587. CFileRecieve hDrpData;
  588. CClipFormat* pCF;
  589. int hDropIndex = -1;
  590. bool savedFile = false;
  591. INT_PTR count = clip.m_Formats.GetSize();
  592. for (int i = 0; i < count; i++)
  593. {
  594. pCF = &clip.m_Formats.ElementAt(i);
  595. if (pCF->m_cfType == theApp.m_DittoFileData)
  596. {
  597. IClipFormat *dittoFileData = &clip.m_Formats.ElementAt(i);
  598. if (dittoFileData != NULL)
  599. {
  600. HGLOBAL data = dittoFileData->Data();
  601. char * stringData = (char *)GlobalLock(data);
  602. //original source is store in the first string ending in the null terminator
  603. CStringA src(stringData);
  604. stringData += src.GetLength() + 1;
  605. CStringA originalMd5(stringData);
  606. stringData += originalMd5.GetLength() + 1;
  607. int dataSize = (int)GlobalSize(data) - (src.GetLength() + 1) - (originalMd5.GetLength() + 1);
  608. CMd5 calcMd5;
  609. CStringA md5String = calcMd5.CalcMD5FromString(stringData, dataSize);
  610. CString unicodeFilePath;
  611. CTextConvert::ConvertFromUTF8(src, unicodeFilePath);
  612. CString unicodeMd5;
  613. CTextConvert::ConvertFromUTF8(md5String, unicodeMd5);
  614. Log(StrF(_T("Saving file contents from Ditto, original file: %s, size: %d, md5: %s"), unicodeFilePath, dataSize, unicodeMd5));
  615. if (md5String == originalMd5)
  616. {
  617. using namespace nsPath;
  618. CPath path(unicodeFilePath);
  619. CString fileName = path.GetName();
  620. CString newFilePath = CGetSetOptions::GetPath(PATH_DRAG_FILES);
  621. newFilePath += fileName;
  622. CFile f;
  623. if (f.Open(newFilePath, CFile::modeWrite | CFile::modeCreate))
  624. {
  625. f.Write(stringData, dataSize);
  626. f.Close();
  627. savedFile = true;
  628. hDrpData.AddFile(newFilePath);
  629. }
  630. else
  631. {
  632. Log(StrF(_T("Error saving file: %s"), unicodeFilePath));
  633. }
  634. }
  635. else
  636. {
  637. Log(StrF(_T("MD5 ERROR, file: %s, original md5: %s, calc md5: %s"), unicodeFilePath, originalMd5, md5String));
  638. }
  639. }
  640. }
  641. else if (pCF->m_cfType == CF_HDROP)
  642. {
  643. hDropIndex = i;
  644. }
  645. }
  646. if (savedFile)
  647. {
  648. if (hDropIndex >= 0)
  649. {
  650. clip.m_Formats.RemoveAt(hDropIndex);
  651. }
  652. CClipFormat cf(CF_HDROP, hDrpData.CreateCF_HDROPBuffer());
  653. clip.m_Formats.Add(cf);
  654. //clip.m_Formats now owns the global data
  655. cf.m_autoDeleteData = false;
  656. }
  657. }
  658. void COleClipSource::Typoglycemia(CClip &clip)
  659. {
  660. IClipFormat *unicodeTextFormat = clip.m_Formats.FindFormatEx(CF_UNICODETEXT);
  661. if (unicodeTextFormat != NULL)
  662. {
  663. HGLOBAL data = unicodeTextFormat->Data();
  664. wchar_t * stringData = (wchar_t *) GlobalLock(data);
  665. int size = (int) GlobalSize(data);
  666. CString cs(stringData);
  667. GlobalUnlock(data);
  668. //free the old text we are going to replace it below with an upper case version
  669. unicodeTextFormat->Free();
  670. CString newString;
  671. CTokenizer token(cs, _T(' '));
  672. CString word;
  673. while (token.Next(word))
  674. {
  675. if(word.GetLength() > 3)
  676. {
  677. int end = word.GetLength();
  678. for (int i = end-1; i >= 0; i--)
  679. {
  680. if(word[i] == _T('.') ||
  681. word[i] == _T('!') ||
  682. word[i] == _T('?'))
  683. {
  684. end--;
  685. }
  686. else
  687. {
  688. break;
  689. }
  690. }
  691. if (end > 3)
  692. {
  693. std::uniform_int_distribution<int> dist(1, end - 2);
  694. std::random_device rd;
  695. for (int i = 1; i < end - 1; i++)
  696. {
  697. int newPos = dist(rd);
  698. CString cs;
  699. cs.Format(_T("pos: %d, rnd: %d\r\n"), i, newPos);
  700. OutputDebugString(cs);
  701. TCHAR temp = word.GetAt(i);
  702. word.SetAt(i, word.GetAt(newPos));
  703. word.SetAt(newPos, temp);
  704. }
  705. }
  706. newString += word;
  707. }
  708. else
  709. {
  710. newString += word;
  711. }
  712. newString += _T(' ');
  713. }
  714. long len = newString.GetLength();
  715. HGLOBAL hGlobal = NewGlobalP(newString.GetBuffer(), ((len + 1) * sizeof(wchar_t)));
  716. unicodeTextFormat->Data(hGlobal);
  717. }
  718. }
  719. INT_PTR COleClipSource::PutFormatOnClipboard(CClipFormats *pFormats)
  720. {
  721. Log(_T("Start of put format on clipboard"));
  722. CClipFormat* pCF;
  723. INT_PTR count = pFormats->GetSize();
  724. bool bDelayedRenderCF_HDROP = false;
  725. bool dittoFileData = false;
  726. INT_PTR i = 0;
  727. //see if the html format is in the list
  728. //if it is the list we will not paste CF_TEXT
  729. for(i = 0; i < count; i++)
  730. {
  731. pCF = &pFormats->ElementAt(i);
  732. if(pCF->m_cfType == theApp.m_RemoteCF_HDROP)
  733. {
  734. bDelayedRenderCF_HDROP = true;
  735. }
  736. if (pCF->m_cfType == theApp.m_DittoFileData)
  737. {
  738. dittoFileData = true;
  739. //save file data
  740. //adjust hdrop
  741. }
  742. }
  743. for(i = 0; i < count; i++)
  744. {
  745. pCF = &pFormats->ElementAt(i);
  746. if(bDelayedRenderCF_HDROP)
  747. {
  748. if(pCF->m_cfType == CF_HDROP)
  749. {
  750. LogSendRecieveInfo("Added delayed cf_hdrop to clipboard");
  751. DelayRenderData(pCF->m_cfType);
  752. }
  753. continue;
  754. }
  755. wchar_t * stringData = (wchar_t *) GlobalLock(pCF->m_hgData);
  756. int size = (int) GlobalSize(pCF->m_hgData);
  757. CString cs(stringData);
  758. GlobalUnlock(pCF->m_hgData);
  759. Log(StrF(_T("Setting clipboard type: %s to the clipboard"), GetFormatName(pCF->m_cfType)));
  760. CacheGlobalData(pCF->m_cfType, pCF->m_hgData);
  761. pCF->m_hgData = 0; // OLE owns it now
  762. }
  763. pFormats->RemoveAll();
  764. m_bLoadedFormats = true;
  765. Log(_T("End of put format on clipboard"));
  766. return count;
  767. }
  768. BOOL COleClipSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  769. {
  770. static bool bInHere = false;
  771. if(bInHere)
  772. {
  773. return FALSE;
  774. }
  775. bInHere = true;
  776. HGLOBAL hData = NULL;
  777. CClipFormat *pFind = m_DelayRenderedFormats.FindFormat(lpFormatEtc->cfFormat);
  778. if(pFind)
  779. {
  780. if(pFind->m_hgData)
  781. {
  782. hData = NewGlobalH(pFind->m_hgData, GlobalSize(pFind->m_hgData));
  783. }
  784. }
  785. else
  786. {
  787. if (m_pasteOptions.m_delayRenderLockout > 0 &&
  788. (GetTickCount() - m_pasteOptions.m_delayRenderLockout) < CGetSetOptions::GetDelayRenderLockout())
  789. {
  790. bInHere = false;
  791. return false;
  792. }
  793. LogSendRecieveInfo("Delayed Render, getting data from remote machine");
  794. CClip clip;
  795. if(m_ClipIDs.GetCount() > 0)
  796. {
  797. clip.LoadFormats(m_ClipIDs[0]);
  798. CClipFormat *pDittoDelayCF_HDROP = clip.m_Formats.FindFormat(theApp.m_RemoteCF_HDROP);
  799. CClipFormat *pCF_HDROP = clip.m_Formats.FindFormat(CF_HDROP);
  800. if(pDittoDelayCF_HDROP && pCF_HDROP)
  801. {
  802. CDittoCF_HDROP *pData = (CDittoCF_HDROP*)GlobalLock(pDittoDelayCF_HDROP->m_hgData);
  803. if(pData)
  804. {
  805. CString csComputerName;
  806. CString csIP;
  807. CTextConvert::ConvertFromUTF8(pData->m_cIP, csIP);
  808. CTextConvert::ConvertFromUTF8(pData->m_cComputerName, csComputerName);
  809. GlobalUnlock(pDittoDelayCF_HDROP->m_hgData);
  810. CClient cl;
  811. hData = cl.RequestCopiedFiles(*pCF_HDROP, csIP, csComputerName);
  812. }
  813. }
  814. else
  815. {
  816. hData = m_ClipIDs.Render(lpFormatEtc->cfFormat);
  817. if (m_convertToHDROPOnDelayRender &&
  818. hData == NULL &&
  819. lpFormatEtc->cfFormat == CF_HDROP)
  820. {
  821. hData = ConvertToFileDrop();
  822. }
  823. }
  824. }
  825. //Add to a cache of already rendered data
  826. //Windows seems to call this function multiple times
  827. //so only the first time do we need to go get the data
  828. HGLOBAL hCopy = NULL;
  829. if(hData)
  830. {
  831. hCopy = NewGlobalH(hData, GlobalSize(hData));
  832. }
  833. CClipFormat format(lpFormatEtc->cfFormat, hCopy);
  834. m_DelayRenderedFormats.Add(format);
  835. format.m_autoDeleteData = false; //owned by m_DelayRenderedFormats
  836. }
  837. BOOL bRet = FALSE;
  838. if(hData)
  839. {
  840. // if phGlobal is null, we can just give the allocated mem
  841. // else, our data must fit within the GlobalSize(*phGlobal)
  842. if(*phGlobal == 0)
  843. {
  844. *phGlobal = hData;
  845. }
  846. else
  847. {
  848. SIZE_T len = min(::GlobalSize(*phGlobal), ::GlobalSize(hData));
  849. if(len)
  850. {
  851. CopyToGlobalHH(*phGlobal, hData, len);
  852. }
  853. ::GlobalFree(hData);
  854. }
  855. bRet = TRUE;
  856. }
  857. bInHere = false;
  858. return bRet;
  859. }
  860. HGLOBAL COleClipSource::ConvertToFileDrop()
  861. {
  862. CString path = CGetSetOptions::GetPath(PATH_DRAG_FILES);
  863. CreateDirectory(path, NULL);
  864. CFileRecieve fileList;
  865. int dragId = CGetSetOptions::GetDragId();
  866. int origDragId = dragId;
  867. for (int i = 0; i < m_ClipIDs.GetCount(); i++)
  868. {
  869. CClip fileClip;
  870. fileClip.LoadFormats(m_ClipIDs[i]);
  871. CClipFormat *unicodeText = fileClip.m_Formats.FindFormat(CF_UNICODETEXT);
  872. if (unicodeText)
  873. {
  874. CString file;
  875. file.Format(_T("%stext_%d.txt"), path, dragId++);
  876. fileClip.WriteTextToFile(file, TRUE, FALSE, FALSE);
  877. fileList.AddFile(file);
  878. }
  879. else
  880. {
  881. CClipFormat *asciiText = fileClip.m_Formats.FindFormat(CF_TEXT);
  882. if (asciiText)
  883. {
  884. CString file;
  885. file.Format(_T("%stext_%d.txt"), path, dragId++);
  886. fileClip.WriteTextToFile(file, FALSE, TRUE, FALSE);
  887. fileList.AddFile(file);
  888. }
  889. else
  890. {
  891. CClipFormat *bitmap = fileClip.m_Formats.FindFormat(CF_DIB);
  892. if (bitmap)
  893. {
  894. CString file;
  895. file.Format(_T("%simage_%d.png"), path, dragId++);
  896. LPVOID pvData = GlobalLock(bitmap->m_hgData);
  897. ULONG size = (ULONG) GlobalSize(bitmap->m_hgData);
  898. WriteCF_DIBToFile(file, pvData, size);
  899. GlobalUnlock(bitmap->m_hgData);
  900. fileList.AddFile(file);
  901. }
  902. }
  903. }
  904. }
  905. if(dragId != origDragId)
  906. {
  907. CGetSetOptions::SetDragId(dragId);
  908. }
  909. HGLOBAL hData = fileList.CreateCF_HDROPBuffer();
  910. return hData;
  911. }