OleClipSource.cpp 30 KB

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