OleClipSource.cpp 27 KB

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