OleClipSource.cpp 28 KB

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