OleClipSource.cpp 29 KB

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