OleClipSource.cpp 25 KB

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