OleClipSource.cpp 26 KB

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