CP_Main.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350
  1. #include "stdafx.h"
  2. #include "CP_Main.h"
  3. #include "MainFrm.h"
  4. #include "Misc.h"
  5. #include ".\cp_main.h"
  6. #include "server.h"
  7. #include "Client.h"
  8. #include <io.h>
  9. #include "Path.h"
  10. #include "Clip_ImportExport.h"
  11. #include "HyperLink.h"
  12. #include "OptionsSheet.h"
  13. #include "DittoCopyBuffer.h"
  14. #include "SendKeys.h"
  15. #include "MainTableFunctions.h"
  16. #include "ShowTaskBarIcon.h"
  17. #include "NoDbFrameWnd.h"
  18. #include <clocale>
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. class DittoCommandLineInfo : public CCommandLineInfo
  25. {
  26. public:
  27. DittoCommandLineInfo()
  28. {
  29. m_bDisconnect = FALSE;
  30. m_bConnect = FALSE;
  31. m_uacPID = 0;
  32. m_bOpenWindow = FALSE;
  33. m_bCloseWindow = FALSE;
  34. m_exit = FALSE;
  35. m_plainTextPaste = FALSE;
  36. m_pasteClip = FALSE;
  37. m_clipID = -1;
  38. m_editClip = FALSE;
  39. m_restartFromRestartManager = FALSE;
  40. }
  41. virtual void ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast)
  42. {
  43. if(bFlag)
  44. {
  45. if(STRICMP(pszParam, _T("Connect")) == 0)
  46. {
  47. m_bConnect = TRUE;
  48. }
  49. else if(STRICMP(pszParam, _T("Disconnect")) == 0)
  50. {
  51. m_bDisconnect = TRUE;
  52. }
  53. else if(wcsncmp(pszParam, _T("uacpaste"), 8) == 0)
  54. {
  55. CString pidCommand(pszParam);
  56. long sep = pidCommand.ReverseFind(':');
  57. if(sep > -1)
  58. {
  59. CString pid = pidCommand.Right(pidCommand.GetLength() - sep - 1);
  60. m_uacPID = ATOI(pid);
  61. }
  62. }
  63. else if(STRICMP(pszParam, _T("open")) == 0)
  64. {
  65. m_bOpenWindow = TRUE;
  66. }
  67. else if(STRICMP(pszParam, _T("close")) == 0)
  68. {
  69. m_bCloseWindow = TRUE;
  70. }
  71. else if (STRICMP(pszParam, _T("exit")) == 0)
  72. {
  73. m_exit = TRUE;
  74. }
  75. else if (STRICMP(pszParam, _T("PlainTextPaste")) == 0)
  76. {
  77. m_plainTextPaste = TRUE;
  78. }
  79. else if (_wcsnicmp(pszParam, _T("paste"), 5) == 0)
  80. {
  81. CString pidCommand(pszParam);
  82. long sep = pidCommand.ReverseFind(':');
  83. if (sep > -1)
  84. {
  85. CString id = pidCommand.Right(pidCommand.GetLength() - sep - 1);
  86. m_clipID = ATOI(id);
  87. m_pasteClip = TRUE;
  88. }
  89. }
  90. else if (_wcsnicmp(pszParam, _T("edit"), 4) == 0)
  91. {
  92. CString pidCommand(pszParam);
  93. long sep = pidCommand.ReverseFind(':');
  94. if (sep > -1)
  95. {
  96. CString id = pidCommand.Right(pidCommand.GetLength() - sep - 1);
  97. m_clipID = ATOI(id);
  98. m_editClip = TRUE;
  99. }
  100. }
  101. else if (_wcsnicmp(pszParam, _T("RestartByRestartManager"), 23) == 0)
  102. {
  103. m_restartFromRestartManager = true;
  104. }
  105. }
  106. CCommandLineInfo::ParseParam(pszParam, bFlag, bLast);
  107. }
  108. BOOL m_bDisconnect;
  109. BOOL m_bConnect;
  110. BOOL m_pasteClip;
  111. int m_uacPID;
  112. int m_clipID;
  113. BOOL m_bCloseWindow;
  114. BOOL m_exit;
  115. BOOL m_bOpenWindow;
  116. BOOL m_plainTextPaste;
  117. BOOL m_editClip;
  118. BOOL m_restartFromRestartManager;
  119. };
  120. CCP_MainApp theApp;
  121. BEGIN_MESSAGE_MAP(CCP_MainApp, CWinApp)
  122. //{{AFX_MSG_MAP(CCP_MainApp)
  123. // NOTE - the ClassWizard will add and remove mapping macros here.
  124. // DO NOT EDIT what you see in these blocks of generated code!
  125. //}}AFX_MSG_MAP
  126. END_MESSAGE_MAP()
  127. CCP_MainApp::CCP_MainApp()
  128. {
  129. m_copyReason = CopyReasonEnum::COPY_TO_UNKOWN;
  130. m_copyReasonStartTime = 0;
  131. m_activeGroupId = -1;
  132. m_activeGroupStartTime = 0;
  133. m_pUacPasteThread = NULL;
  134. m_bAppRunning = false;
  135. m_bAppExiting = false;
  136. m_connectOnStartup = -1;
  137. m_MainhWnd = NULL;
  138. m_pMainFrame = NULL;
  139. BOOL set = ::AllowSetForegroundWindow(ASFW_ANY);
  140. m_bShowingQuickPaste = false;
  141. m_GroupDefaultID = 0;
  142. m_GroupID = -1;
  143. m_GroupParentID = 0;
  144. m_GroupText = "History";
  145. m_FocusID = -1;
  146. ClearOldGroupState();
  147. m_bAsynchronousRefreshView = true;
  148. m_lClipsSent = 0;
  149. m_lClipsRecieved = 0;
  150. m_oldtStartUp = COleDateTime::GetCurrentTime();
  151. m_bExitServerThread = false;
  152. m_lLastGoodIndexForNextworkPassword = -2;
  153. m_RTFFormat = ::RegisterClipboardFormat(_T("Rich Text Format"));
  154. m_HTML_Format = ::RegisterClipboardFormat(_T("HTML Format"));
  155. m_PingFormat = ::RegisterClipboardFormat(_T("Ditto Ping Format"));
  156. m_cfIgnoreClipboard = ::RegisterClipboardFormat(_T("Clipboard Viewer Ignore"));
  157. m_cfDelaySavingData = ::RegisterClipboardFormat(_T("Ditto Delay Saving Data"));
  158. m_RemoteCF_HDROP = ::RegisterClipboardFormat(_T("Ditto Remote CF_HDROP"));
  159. m_DittoFileData = ::RegisterClipboardFormat(_T("Ditto File Data"));
  160. m_PNG_Format = GetFormatID(_T("PNG"));
  161. m_pNoDbMainFrame = NULL;
  162. m_databaseOnNetworkShare = false;
  163. m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
  164. }
  165. CCP_MainApp::~CCP_MainApp()
  166. {
  167. }
  168. BOOL CCP_MainApp::InitInstance()
  169. {
  170. INITCOMMONCONTROLSEX InitCtrls;
  171. InitCtrls.dwSize = sizeof(InitCtrls);
  172. // Set this to include all the common control classes you want to use
  173. // in your application.
  174. InitCtrls.dwICC = ICC_WIN95_CLASSES;
  175. InitCommonControlsEx(&InitCtrls);
  176. AfxEnableControlContainer();
  177. AfxOleInit();
  178. AfxInitRichEditEx();
  179. Gdiplus::GdiplusStartupInput gdiplusStartupInput;
  180. Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
  181. LoadLibrary(TEXT("MSFTEDIT.DLL"));
  182. setlocale(LC_TIME, ".OCP"); // defines the date/time formatting
  183. //MessageBox(NULL, _T("ditto starting"), _T("d"), MB_OK);
  184. DittoCommandLineInfo cmdInfo;
  185. ParseCommandLine(cmdInfo);
  186. CGetSetOptions::LoadSettings();
  187. theApp.m_activeWnd.TrackActiveWnd(false);
  188. if(cmdInfo.m_uacPID > 0)
  189. {
  190. Log(StrF(_T("Startup up ditto as admin to paste to admin windows, parent process id: %d"), cmdInfo.m_uacPID));
  191. CString mutex;
  192. mutex.Format(_T("DittoAdminPaste_%d"), cmdInfo.m_uacPID);
  193. m_adminPasteMutex = CreateMutex(NULL, FALSE, mutex);
  194. m_pUacPasteThread = new CUAC_Thread(cmdInfo.m_uacPID);
  195. m_pUacPasteThread->Start();
  196. m_pUacPasteThread->WaitForThreadToExit(INT_MAX);
  197. return FALSE;
  198. }
  199. if (cmdInfo.m_restartFromRestartManager)
  200. {
  201. Log(StrF(_T("Ditto was restarted from restart manager")));
  202. }
  203. else if(cmdInfo.m_strFileName.IsEmpty() == FALSE)
  204. {
  205. try
  206. {
  207. CGetSetOptions::m_bEnableDebugLogging = CGetSetOptions::GetEnableDebugLogging();
  208. CClip_ImportExport Clip;
  209. CppSQLite3DB db;
  210. db.open(cmdInfo.m_strFileName);
  211. CClip_ImportExport clip;
  212. if(clip.ImportFromSqliteDB(db, false, true))
  213. {
  214. ShowCommandLineError("Ditto", theApp.m_Language.GetString("Importing_Good", "Clip placed on clipboard"));
  215. }
  216. else
  217. {
  218. ShowCommandLineError("Ditto", theApp.m_Language.GetString("Error_Importing", "Error importing exported clip"));
  219. }
  220. }
  221. catch (CppSQLite3Exception& e)
  222. {
  223. ASSERT(FALSE);
  224. CString csError;
  225. csError.Format(_T("%s - Exception - %d - %s"), theApp.m_Language.GetString("Error_Parsing", "Error parsing exported clip"), e.errorCode(), e.errorMessage());
  226. ShowCommandLineError("Ditto", csError);
  227. }
  228. return FALSE;
  229. }
  230. else if(cmdInfo.m_bConnect || cmdInfo.m_bDisconnect)
  231. {
  232. //First get the saved hwnd and send it a message
  233. //If ditto is running then this will return 1, meaning the running ditto process
  234. //handled this message
  235. //If it didn't handle the message(ditto is not running) then startup this processes of ditto
  236. //disconnected from the clipboard
  237. LRESULT ret = 0;
  238. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  239. if(hWnd)
  240. {
  241. ret = ::SendMessage(hWnd, WM_SET_CONNECTED, cmdInfo.m_bConnect, cmdInfo.m_bDisconnect);
  242. }
  243. //passed off to the running instance of ditto, exit this instance
  244. if(ret == 1)
  245. {
  246. return FALSE;
  247. }
  248. if(cmdInfo.m_bConnect)
  249. {
  250. m_connectOnStartup = TRUE;
  251. }
  252. else if(cmdInfo.m_bDisconnect)
  253. {
  254. m_connectOnStartup = FALSE;
  255. }
  256. }
  257. else if(cmdInfo.m_bOpenWindow || cmdInfo.m_bCloseWindow)
  258. {
  259. //First get the saved hwnd and send it a message
  260. //If ditto is running then this will return 1, meaning the running ditto process
  261. //handled this message
  262. //If it didn't handle the message(ditto is not running) then startup this processes of ditto
  263. //disconnected from the clipboard
  264. LRESULT ret = 0;
  265. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  266. if(hWnd)
  267. {
  268. ret = ::SendMessage(hWnd, WM_OPEN_CLOSE_WINDOW, cmdInfo.m_bOpenWindow, cmdInfo.m_bCloseWindow);
  269. }
  270. return FALSE;
  271. }
  272. else if (cmdInfo.m_exit)
  273. {
  274. //First get the saved hwnd and send it a message
  275. //If ditto is running then this will return 1, meaning the running ditto process
  276. //handled this message
  277. //If it didn't handle the message(ditto is not running) then startup this processes of ditto
  278. //disconnected from the clipboard
  279. LRESULT ret = 0;
  280. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  281. if (hWnd)
  282. {
  283. ret = ::SendMessage(hWnd, WM_CLOSE, NULL, NULL);
  284. }
  285. return FALSE;
  286. }
  287. else if (cmdInfo.m_plainTextPaste)
  288. {
  289. LRESULT ret = 0;
  290. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  291. if (hWnd)
  292. {
  293. ret = ::SendMessage(hWnd, WM_PLAIN_TEXT_PASTE, NULL, NULL);
  294. }
  295. return FALSE;
  296. }
  297. else if (cmdInfo.m_pasteClip)
  298. {
  299. LRESULT ret = 0;
  300. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  301. if (hWnd)
  302. {
  303. ret = ::SendMessage(hWnd, WM_PASTE_CLIP, cmdInfo.m_clipID, NULL);
  304. }
  305. return FALSE;
  306. }
  307. else if (cmdInfo.m_editClip)
  308. {
  309. LRESULT ret = 0;
  310. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  311. if (hWnd)
  312. {
  313. ret = ::SendMessage(hWnd, WM_EDIT_CLIP, cmdInfo.m_clipID, NULL);
  314. }
  315. return FALSE;
  316. }
  317. auto runningVersion = GetRunningVersion();
  318. CString cs = GetVersionString(runningVersion);
  319. cs.Insert(0, _T("InitInstance - Running Version - "));
  320. Log(cs);
  321. CString csMutex("Ditto Is Now Running");
  322. if(CGetSetOptions::GetIsPortableDitto() || CGetSetOptions::GetIsWindowsApp() || CGetSetOptions::GetIsChocolateyApp())
  323. {
  324. csMutex += " ";
  325. csMutex += CGetSetOptions::GetExeFileName();
  326. }
  327. CWinApp::RegisterWithRestartManager(false, csMutex);
  328. //create mutex doesn't like slashes, remove them, it always returns NULL with them in
  329. csMutex.Replace(_T("\\"), _T("_"));
  330. m_hMutex = CreateMutex(NULL, TRUE, csMutex);
  331. DWORD dwError = GetLastError();
  332. if(m_hMutex == NULL ||
  333. dwError == ERROR_ALREADY_EXISTS)
  334. {
  335. Log(StrF(_T("Ditto is already running, closing, mutex: %s"), csMutex));
  336. HWND hWnd = (HWND)(LONG_PTR)CGetSetOptions::GetMainHWND();
  337. if(hWnd)
  338. ::SendMessage(hWnd, WM_SHOW_TRAY_ICON, TRUE, TRUE);
  339. return TRUE;
  340. }
  341. Log(StrF(_T("Starting up ditto with mutex: %s"), csMutex));
  342. CString csFile = CGetSetOptions::GetLanguageFile();
  343. if(m_Language.LoadLanguageFile(csFile) == false)
  344. {
  345. CString cs;
  346. cs.Format(_T("Error loading language file - %s - \n\n%s"), csFile, m_Language.m_csLastError);
  347. Log(cs);
  348. m_Language.LoadLanguageFile(_T("English.xml"));
  349. }
  350. m_icuString.Load();
  351. int nRet = CheckDBExists(CGetSetOptions::GetDBPath());
  352. if(nRet == FALSE)
  353. {
  354. m_pNoDbMainFrame = new CNoDbFrameWnd();
  355. m_pMainWnd = m_pNoDbMainFrame;
  356. m_pNoDbMainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
  357. m_pNoDbMainFrame->ShowWindow(SW_SHOW);
  358. m_pNoDbMainFrame->UpdateWindow();
  359. }
  360. else
  361. {
  362. //Sleep(1000);
  363. CreateMainWnd();
  364. }
  365. return TRUE;
  366. }
  367. void CCP_MainApp::CreateMainWnd()
  368. {
  369. CMainFrame* pFrame = new CMainFrame;
  370. m_pMainWnd = m_pMainFrame = pFrame;
  371. pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
  372. //removed to keep ditto from taking focus on startup
  373. //pFrame->ShowWindow(SW_SHOW);
  374. //pFrame->UpdateWindow();
  375. }
  376. void CCP_MainApp::CloseNoDbWindow()
  377. {
  378. if (m_pNoDbMainFrame != NULL)
  379. {
  380. m_pNoDbMainFrame->CloseWindow();
  381. delete m_pNoDbMainFrame;
  382. m_pNoDbMainFrame = NULL;
  383. }
  384. }
  385. void CCP_MainApp::AfterMainCreate()
  386. {
  387. m_MainhWnd = m_pMainFrame->m_hWnd;
  388. ASSERT( ::IsWindow(m_MainhWnd) );
  389. CGetSetOptions::SetMainHWND((long)(LONG_PTR)m_MainhWnd);
  390. g_HotKeys.Init(m_MainhWnd);
  391. // create hotkeys here. They are automatically deleted on exit
  392. m_pDittoHotKey = new CHotKey(CString("DittoHotKey"), 704); //704 is ctrl-tilda
  393. m_pDittoHotKey2 = new CHotKey(CString("DittoHotKey2"));
  394. m_pDittoHotKey3 = new CHotKey(CString("DittoHotKey3"));
  395. m_pPosOne = new CHotKey("Position1", 0, true);
  396. m_pPosTwo = new CHotKey("Position2", 0, true);
  397. m_pPosThree = new CHotKey("Position3", 0, true);
  398. m_pPosFour = new CHotKey("Position4", 0, true);
  399. m_pPosFive = new CHotKey("Position5", 0, true);
  400. m_pPosSix = new CHotKey("Position6", 0, true);
  401. m_pPosSeven = new CHotKey("Position7", 0, true);
  402. m_pPosEight = new CHotKey("Position8", 0, true);
  403. m_pPosNine = new CHotKey("Position9", 0, true);
  404. m_pPosTen = new CHotKey("Position10", 0, true);
  405. m_pCopyBuffer1 = new CHotKey("CopyBufferCopyHotKey_0", 0, true);
  406. m_pPasteBuffer1 = new CHotKey("CopyBufferPasteHotKey_0", 0, true);
  407. m_pCutBuffer1 = new CHotKey("CopyBufferCutHotKey_0", 0, true);
  408. m_pCopyBuffer2 = new CHotKey("CopyBufferCopyHotKey_1", 0, true);
  409. m_pPasteBuffer2 = new CHotKey("CopyBufferPasteHotKey_1", 0, true);
  410. m_pCutBuffer2 = new CHotKey("CopyBufferCutHotKey_1", 0, true);
  411. m_pCopyBuffer3 = new CHotKey("CopyBufferCopyHotKey_2", 0, true);
  412. m_pPasteBuffer3 = new CHotKey("CopyBufferPasteHotKey_2", 0, true);
  413. m_pCutBuffer3 = new CHotKey("CopyBufferCutHotKey_2", 0, true);
  414. m_pCopyBuffer4 = new CHotKey("CopyBufferCopyHotKey_3", 0, true);
  415. m_pPasteBuffer4 = new CHotKey("CopyBufferPasteHotKey_3", 0, true);
  416. m_pCutBuffer4 = new CHotKey("CopyBufferCutHotKey_3", 0, true);
  417. m_pCopyBuffer5 = new CHotKey("CopyBufferCopyHotKey_4", 0, true);
  418. m_pPasteBuffer5 = new CHotKey("CopyBufferPasteHotKey_4", 0, true);
  419. m_pCutBuffer5 = new CHotKey("CopyBufferCutHotKey_4", 0, true);
  420. m_pTextOnlyPaste = new CHotKey("TextOnlyPaste", 0, true);
  421. m_pSaveClipboard = new CHotKey("SaveClipboard", 0, false);
  422. m_pCopyAndSaveClipboard = new CHotKey("CopyAndSaveClipboard", 0, false);
  423. m_editThread.StartWatchingFolderForChanges();
  424. LoadGlobalClips();
  425. g_HotKeys.RegisterAll();
  426. StartCopyThread();
  427. StartStopServerThread();
  428. #ifdef UNICODE
  429. m_Addins.LoadAll();
  430. #endif
  431. m_bAppRunning = true;
  432. }
  433. void CCP_MainApp::LoadGlobalClips()
  434. {
  435. try
  436. {
  437. {
  438. CppSQLite3Query q = m_db.execQuery(_T("SELECT lID, lShortCut, mText FROM Main WHERE lShortCut > 0 AND globalShortCut = 1"));
  439. while(q.eof() == false)
  440. {
  441. int id = q.getIntField(_T("lID"));
  442. int shortcut = q.getIntField(_T("lShortCut"));
  443. CString desc = q.getStringField(_T("mText"));
  444. //Constructor will add to a global list and free
  445. CHotKey* globalHotKey = new CHotKey(StrF(_T("GlobalClip: %d"), id), shortcut, true, CHotKey::PASTE_OPEN_CLIP, desc);
  446. if(globalHotKey != NULL)
  447. {
  448. globalHotKey->m_clipId = id;
  449. }
  450. q.nextRow();
  451. }
  452. }
  453. {
  454. CppSQLite3Query q2 = m_db.execQuery(_T("SELECT lID, MoveToGroupShortCut, mText FROM Main WHERE MoveToGroupShortCut > 0 AND GlobalMoveToGroupShortCut = 1"));
  455. while(q2.eof() == false)
  456. {
  457. int id = q2.getIntField(_T("lID"));
  458. int shortcut = q2.getIntField(_T("MoveToGroupShortCut"));
  459. CString desc = q2.getStringField(_T("mText"));
  460. //Constructor will add to a global list and free
  461. CHotKey* globalHotKey = new CHotKey(StrF(_T("MoveToGroup: %d"), id), shortcut, true, CHotKey::MOVE_TO_GROUP, desc);
  462. if(globalHotKey != NULL)
  463. {
  464. globalHotKey->m_clipId = id;
  465. }
  466. q2.nextRow();
  467. }
  468. }
  469. }
  470. CATCH_SQLITE_EXCEPTION
  471. }
  472. void CCP_MainApp::StartStopServerThread()
  473. {
  474. if(CGetSetOptions::GetDisableRecieve() == FALSE && CGetSetOptions::GetAllowFriends())
  475. {
  476. AfxBeginThread(MTServerThread, m_MainhWnd);
  477. }
  478. else
  479. {
  480. m_bExitServerThread = true;
  481. closesocket(theApp.m_sSocket);
  482. }
  483. }
  484. void CCP_MainApp::StopServerThread()
  485. {
  486. m_bExitServerThread = true;
  487. closesocket(theApp.m_sSocket);
  488. }
  489. void CCP_MainApp::BeforeMainClose()
  490. {
  491. ASSERT( m_bAppRunning && !m_bAppExiting );
  492. m_bAppRunning = false;
  493. m_bAppExiting = true;
  494. g_HotKeys.UnregisterAll();
  495. StopServerThread();
  496. StopCopyThread();
  497. }
  498. void CCP_MainApp::StartCopyThread()
  499. {
  500. ASSERT( m_MainhWnd );
  501. CClipTypes* pTypes = LoadTypesFromDB();
  502. // initialize to:
  503. // - m_MainhWnd = send WM_CLIPBOARD_COPIED messages to m_MainhWnd
  504. // - true = use Asynchronous communication (PostMessage)
  505. // - true = enable copying on clipboard changes
  506. // - pTypes = the supported types to use
  507. m_CopyThread.Init(CCopyConfig(m_MainhWnd, true, true, pTypes));
  508. if(m_connectOnStartup == FALSE || CGetSetOptions::GetConnectedToClipboard() == FALSE)
  509. {
  510. m_CopyThread.m_connectOnStartup = false;
  511. Log(StrF(_T("Starting Ditto up disconnected from the clipboard, commandLine: %d, saved value: %d"), m_connectOnStartup, CGetSetOptions::GetConnectedToClipboard()));
  512. SetConnectCV(false);
  513. }
  514. else if(m_connectOnStartup == TRUE)
  515. {
  516. SetConnectCV(true);
  517. Log(_T("Starting Ditto up connected from the clipboard, passed in true from command line to start connected"));
  518. }
  519. VERIFY(m_CopyThread.CreateThread(CREATE_SUSPENDED));
  520. m_CopyThread.ResumeThread();
  521. }
  522. void CCP_MainApp::StopCopyThread()
  523. {
  524. EnableCbCopy(false);
  525. m_CopyThread.Quit();
  526. }
  527. // returns the current Clipboard Viewer Connect state (though it might not yet
  528. // be actually connected -- check IsClipboardViewerConnected())
  529. bool CCP_MainApp::ToggleConnectCV()
  530. {
  531. bool bConnect = !GetConnectCV();
  532. SetConnectCV(bConnect);
  533. return bConnect;
  534. }
  535. // Sets a menu entry according to the current Clipboard Viewer Connection status
  536. // - the menu text indicates the available command (opposite the current state)
  537. // - a check mark appears in the rare cases that the menu text actually represents
  538. // the current state, e.g. if we are supposed to be connected, but we somehow
  539. // lose that connection, "Disconnect from Clipboard" will have a check next to it.
  540. void CCP_MainApp::UpdateMenuConnectCV(CMenu* pMenu, UINT nMenuID)
  541. {
  542. if(pMenu == NULL)
  543. return;
  544. bool bConnect = theApp.GetConnectCV();
  545. CString cs;
  546. if(bConnect)
  547. {
  548. cs = theApp.m_Language.GetString("Disconnect_Clipboard", "Disconnect from Clipboard.");
  549. pMenu->ModifyMenu(nMenuID, MF_BYCOMMAND, nMenuID, cs);
  550. }
  551. else
  552. {
  553. cs = theApp.m_Language.GetString("Connect_Clipboard", "Connect to Clipboard.");
  554. pMenu->ModifyMenu(nMenuID, MF_BYCOMMAND, nMenuID, cs);
  555. }
  556. }
  557. // Allocates a new CClipTypes
  558. CClipTypes* CCP_MainApp::LoadTypesFromDB()
  559. {
  560. CClipTypes* pTypes = new CClipTypes;
  561. try
  562. {
  563. CppSQLite3Query q = theApp.m_db.execQuery(_T("SELECT TypeText FROM Types"));
  564. while(q.eof() == false)
  565. {
  566. pTypes->Add(GetFormatID(q.getStringField(_T("TypeText"))));
  567. q.nextRow();
  568. }
  569. }
  570. CATCH_SQLITE_EXCEPTION
  571. if(pTypes->GetSize() <= 0)
  572. {
  573. pTypes->Add(CF_TEXT);
  574. pTypes->Add(RegisterClipboardFormat(CF_RTF));
  575. pTypes->Add(CF_UNICODETEXT);
  576. pTypes->Add(CF_HDROP);
  577. pTypes->Add(CF_DIB);
  578. pTypes->Add(GetFormatID(_T("HTML Format")));
  579. pTypes->Add(GetFormatID(_T("PNG")));
  580. }
  581. return pTypes;
  582. }
  583. void CCP_MainApp::ReloadTypes()
  584. {
  585. CClipTypes* pTypes = LoadTypesFromDB();
  586. if(pTypes)
  587. {
  588. m_CopyThread.SetSupportedTypes(pTypes);
  589. }
  590. }
  591. void CCP_MainApp::RefreshView(CopyReasonEnum::CopyReason copyReason)
  592. {
  593. CQPasteWnd *pWnd = QPasteWnd();
  594. if(pWnd)
  595. {
  596. if(m_bAsynchronousRefreshView)
  597. {
  598. pWnd->PostMessage(WM_REFRESH_VIEW, copyReason, 0);
  599. }
  600. else
  601. {
  602. pWnd->SendMessage(WM_REFRESH_VIEW, copyReason, 0);
  603. }
  604. }
  605. }
  606. void CCP_MainApp::RefreshClipInUI(int clipId, int updateFlags)
  607. {
  608. CQPasteWnd *pWnd = QPasteWnd();
  609. if(pWnd)
  610. {
  611. if(m_bAsynchronousRefreshView)
  612. {
  613. pWnd->PostMessage(WM_RELOAD_CLIP_IN_UI, clipId, updateFlags);
  614. }
  615. else
  616. {
  617. pWnd->SendMessage(WM_RELOAD_CLIP_IN_UI, clipId, updateFlags);
  618. }
  619. }
  620. }
  621. void CCP_MainApp::OnPasteCompleted()
  622. {
  623. }
  624. void CCP_MainApp::OnCopyCompleted(long lLastID, int count, CopyReasonEnum::CopyReason copyReason)
  625. {
  626. if(count <= 0)
  627. {
  628. return;
  629. }
  630. // update copy statistics
  631. CGetSetOptions::SetTripCopyCount(-count);
  632. CGetSetOptions::SetTotalCopyCount(-count);
  633. if(m_CopyBuffer.Active())
  634. {
  635. m_CopyBuffer.EndCopy(lLastID);
  636. }
  637. RefreshView(copyReason);
  638. }
  639. void CCP_MainApp::SaveCurrentGroupState()
  640. {
  641. m_oldGroupID = m_GroupID;
  642. m_oldGroupParentID = m_GroupParentID;
  643. m_oldGroupText = m_GroupText;
  644. }
  645. void CCP_MainApp::ClearOldGroupState()
  646. {
  647. m_oldGroupID = -2;
  648. m_oldGroupParentID = -2;
  649. m_oldGroupText = _T("");
  650. }
  651. BOOL CCP_MainApp::TryEnterOldGroupState()
  652. {
  653. BOOL enteredGroup = FALSE;
  654. if(m_oldGroupID > -2)
  655. {
  656. m_GroupID = m_oldGroupID;
  657. m_GroupParentID = m_oldGroupParentID;
  658. m_GroupText = m_oldGroupText;
  659. ClearOldGroupState();
  660. theApp.RefreshView();
  661. if(QPasteWnd())
  662. QPasteWnd()->UpdateStatus(true);
  663. enteredGroup = TRUE;
  664. }
  665. return enteredGroup;
  666. }
  667. BOOL CCP_MainApp::EnterGroupID(long lID, BOOL clearOldGroupState/* = TRUE*/, BOOL saveCurrentGroupState/* = FALSE*/)
  668. {
  669. BOOL bResult = FALSE;
  670. if(m_GroupID == lID)
  671. return TRUE;
  672. DWORD startTick = GetTickCount();
  673. if(clearOldGroupState)
  674. {
  675. ClearOldGroupState();
  676. }
  677. if(saveCurrentGroupState)
  678. {
  679. SaveCurrentGroupState();
  680. }
  681. // if we are switching to the parent, focus on the previous group
  682. if(m_GroupParentID == lID && m_GroupID > 0)
  683. m_FocusID = m_GroupID;
  684. switch(lID)
  685. {
  686. case -1:
  687. m_FocusID = -1;
  688. m_GroupID = -1;
  689. m_GroupParentID = -1;
  690. m_GroupText = "History";
  691. bResult = TRUE;
  692. break;
  693. default: // Normal Group
  694. try
  695. {
  696. CppSQLite3Query q = theApp.m_db.execQueryEx(_T("SELECT lParentID, mText, bIsGroup FROM Main WHERE lID = %d"), lID);
  697. if(q.eof() == false)
  698. {
  699. if(q.getIntField(_T("bIsGroup")) > 0)
  700. {
  701. m_GroupID = lID;
  702. m_GroupParentID = q.getIntField(_T("lParentID"));
  703. m_GroupText = q.getStringField(_T("mText"));
  704. bResult = TRUE;
  705. }
  706. }
  707. }
  708. CATCH_SQLITE_EXCEPTION
  709. break;
  710. }
  711. if(bResult)
  712. {
  713. theApp.RefreshView();
  714. if(QPasteWnd())
  715. QPasteWnd()->UpdateStatus(true);
  716. }
  717. DWORD endTick = GetTickCount();
  718. if((endTick-startTick) > 150)
  719. Log(StrF(_T("Paste Timing EnterParentId: %d"), endTick-startTick));
  720. return bResult;
  721. }
  722. // returns a usable group id (not negative)
  723. long CCP_MainApp::GetValidGroupID()
  724. {
  725. return m_GroupID;
  726. }
  727. // sets a valid id
  728. void CCP_MainApp::SetGroupDefaultID(long lID)
  729. {
  730. if(m_GroupDefaultID == lID)
  731. {
  732. return;
  733. }
  734. if(lID <= 0)
  735. {
  736. m_GroupDefaultID = 0;
  737. }
  738. else
  739. {
  740. m_GroupDefaultID = lID;
  741. }
  742. if(QPasteWnd())
  743. {
  744. QPasteWnd()->UpdateStatus();
  745. }
  746. }
  747. void CCP_MainApp::SetStatus(const TCHAR* status, bool bRepaintImmediately)
  748. {
  749. m_Status = status;
  750. if(QPasteWnd())
  751. {
  752. QPasteWnd()->UpdateStatus(bRepaintImmediately);
  753. }
  754. }
  755. void CCP_MainApp::ShowPersistent(bool bVal)
  756. {
  757. CGetSetOptions::SetShowPersistent(bVal);
  758. // give some visual indication
  759. if(m_bShowingQuickPaste)
  760. {
  761. ASSERT(QPasteWnd());
  762. QPasteWnd()->SetCaptionColorActive(CGetSetOptions::m_bShowPersistent, theApp.GetConnectCV());
  763. QPasteWnd()->RefreshNc();
  764. }
  765. }
  766. /////////////////////////////////////////////////////////////////////////////
  767. // CCP_MainApp message handlers
  768. int CCP_MainApp::ExitInstance()
  769. {
  770. Log(_T("ExitInstance"));
  771. DeleteDittoTempFiles(FALSE);
  772. m_db.close();
  773. if(m_pUacPasteThread != NULL)
  774. {
  775. if(m_pUacPasteThread->ThreadWasStarted() == false)
  776. {
  777. m_pUacPasteThread->FireExit();
  778. }
  779. delete m_pUacPasteThread;
  780. }
  781. Gdiplus::GdiplusShutdown(m_gdiplusToken);
  782. return CWinApp::ExitInstance();
  783. }
  784. // return TRUE if there is more idle processing to do
  785. BOOL CCP_MainApp::OnIdle(LONG lCount)
  786. {
  787. // let winapp handle its idle processing
  788. if(CWinApp::OnIdle(lCount))
  789. return TRUE;
  790. return FALSE;
  791. }
  792. void CCP_MainApp::SetConnectCV(bool bConnect)
  793. {
  794. m_CopyThread.SetConnectCV(bConnect);
  795. CGetSetOptions::SetConnectedToClipboard(bConnect == true);
  796. if(bConnect)
  797. {
  798. m_pMainFrame->m_trayIcon.SetIcon(IDR_MAINFRAME);
  799. m_pMainFrame->m_trayIcon.SetTooltipText(_T("Ditto"));
  800. }
  801. else
  802. {
  803. m_pMainFrame->m_trayIcon.SetIcon(IDI_DITTO_NOCOPYCB);
  804. CString cs;
  805. cs = _T("Ditto ");
  806. cs += theApp.m_Language.GetString("disconnected", "[Disconnected]");
  807. m_pMainFrame->m_trayIcon.SetTooltipText(cs);
  808. }
  809. if(QPasteWnd())
  810. {
  811. QPasteWnd()->SetCaptionColorActive(CGetSetOptions::m_bShowPersistent, theApp.GetConnectCV());
  812. QPasteWnd()->RefreshNc();
  813. }
  814. }
  815. void CCP_MainApp::OnDeleteID(long lID)
  816. {
  817. if(QPasteWnd())
  818. {
  819. QPasteWnd()->PostMessage(NM_ITEM_DELETED, lID, 0);
  820. }
  821. }
  822. bool CCP_MainApp::ImportClips(HWND hWnd)
  823. {
  824. OPENFILENAME FileName;
  825. TCHAR szFileName[400];
  826. TCHAR szDir[400];
  827. memset(&FileName, 0, sizeof(FileName));
  828. memset(szFileName, 0, sizeof(szFileName));
  829. memset(&szDir, 0, sizeof(szDir));
  830. CString csInitialDir = CGetSetOptions::GetLastImportDir();
  831. STRCPY(szDir, csInitialDir);
  832. FileName.lStructSize = sizeof(FileName);
  833. FileName.lpstrTitle = _T("Import Clips");
  834. FileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;
  835. FileName.nMaxFile = 400;
  836. FileName.lpstrFile = szFileName;
  837. FileName.lpstrInitialDir = szDir;
  838. FileName.lpstrFilter = _T("Exported Ditto Clips (.dto)\0*.dto\0\0");
  839. FileName.lpstrDefExt = _T("dto");
  840. if(GetOpenFileName(&FileName) == 0)
  841. {
  842. return false;
  843. }
  844. using namespace nsPath;
  845. CPath path(FileName.lpstrFile);
  846. CString csPath = path.GetPath();
  847. CGetSetOptions::SetLastImportDir(csPath);
  848. try
  849. {
  850. CppSQLite3DB db;
  851. db.open(FileName.lpstrFile);
  852. CClip_ImportExport clip;
  853. if(clip.ImportFromSqliteDB(db, true, false))
  854. {
  855. CShowTaskBarIcon show;
  856. CString cs;
  857. cs.Format(_T("%s %d "), theApp.m_Language.GetString("Import_Successfully", "Successfully imported"), clip.m_importCount);
  858. if(clip.m_importCount = 1)
  859. cs += theApp.m_Language.GetString("Clip", "clip");
  860. else
  861. cs += theApp.m_Language.GetString("Clips", "clips");
  862. MessageBox(hWnd, cs, _T("Ditto"), MB_OK);
  863. }
  864. else
  865. {
  866. CShowTaskBarIcon show;
  867. MessageBox(hWnd, theApp.m_Language.GetString("Error_Importing", "Error importing exported clip"), _T("Ditto"), MB_OK);
  868. }
  869. }
  870. catch (CppSQLite3Exception& e)
  871. {
  872. ASSERT(FALSE);
  873. CString csError;
  874. csError.Format(_T("%s - Exception - %d - %s"), theApp.m_Language.GetString("Error_Parsing", "Error parsing exported clip"), e.errorCode(), e.errorMessage());
  875. MessageBox(hWnd, csError, _T("Ditto"), MB_OK);
  876. }
  877. return true;
  878. }
  879. void CCP_MainApp::ShowCommandLineError(CString csTitle, CString csMessage)
  880. {
  881. Log(StrF(_T("ShowCommandLineError %s - %s"), csTitle, csMessage));
  882. CToolTipEx *pErrorWnd = new CToolTipEx;
  883. pErrorWnd->Create(NULL);
  884. pErrorWnd->SetToolTipText(csTitle + "\n\n" + csMessage);
  885. CPoint pt;
  886. CRect rcScreen = DefaultMonitorRect();
  887. pt = rcScreen.BottomRight();
  888. CRect cr = pErrorWnd->GetBoundsRect();
  889. pt.x -= max(cr.Width()+50, 150);
  890. pt.y -= max(cr.Height()+50, 150);
  891. pErrorWnd->Show(pt);
  892. PumpMessageEx(pErrorWnd->m_hWnd);
  893. Sleep(4000);
  894. pErrorWnd->DestroyWindow();
  895. }
  896. BOOL CCP_MainApp::GetClipData(long parentId, CClipFormat &Clip)
  897. {
  898. BOOL bRet = FALSE;
  899. try
  900. {
  901. CppSQLite3Query q = theApp.m_db.execQueryEx(_T("SELECT ooData FROM Data WHERE lParentID = %d AND strClipboardFormat = '%s'"), parentId, GetFormatName(Clip.m_cfType));
  902. if(q.eof() == false)
  903. {
  904. int nDataLen = 0;
  905. const unsigned char *cData = q.getBlobField(_T("ooData"), nDataLen);
  906. if(cData != NULL)
  907. {
  908. Clip.m_hgData = NewGlobal(nDataLen);
  909. ::CopyToGlobalHP(Clip.m_hgData, (LPVOID)cData, nDataLen);
  910. bRet = TRUE;
  911. }
  912. }
  913. }
  914. CATCH_SQLITE_EXCEPTION
  915. return bRet;
  916. }
  917. bool CCP_MainApp::EditItems(CClipIDs &Ids, bool bShowError, bool forceTextEdit)
  918. {
  919. bool ret = false;
  920. int lastFileCheckId = 1;
  921. for (int i = 0; i < min(Ids.GetCount(), 20); i++)
  922. {
  923. const int id = Ids[i];
  924. CClip clip;
  925. if (id >= 0 && clip.LoadFormats(id, true, true) == false)
  926. {
  927. Log(StrF(_T("Failed to load formats for clipId: %d"), id));
  928. continue;
  929. }
  930. bool unicodeFile = false;
  931. bool asciFile = false;
  932. bool rtfFile = false;
  933. CString exePath;
  934. CString extension;
  935. if (forceTextEdit == false && clip.ContainsClipFormat(theApp.m_RTFFormat))
  936. {
  937. extension = _T("rtf");
  938. rtfFile = true;
  939. exePath = CGetSetOptions::GetRTFEditorPath();
  940. }
  941. else if (clip.ContainsClipFormat(CF_UNICODETEXT))
  942. {
  943. extension = _T("txt");
  944. unicodeFile = true;
  945. exePath = CGetSetOptions::GetTextEditorPath();
  946. }
  947. else if (clip.ContainsClipFormat(CF_TEXT))
  948. {
  949. extension = _T("txt");
  950. asciFile = true;
  951. exePath = CGetSetOptions::GetTextEditorPath();
  952. }
  953. else if (id == -1)
  954. {
  955. extension = _T("txt");
  956. unicodeFile = true;
  957. exePath = CGetSetOptions::GetTextEditorPath();
  958. }
  959. else
  960. {
  961. continue;
  962. }
  963. CString startingFilePath = StrF(_T("%sEditClip_%d.%s"), CGetSetOptions::GetPath(PATH_EDIT_CLIPS), id, extension);
  964. if (id == -1)
  965. {
  966. startingFilePath = StrF(_T("%sNewClip_1.%s"), CGetSetOptions::GetPath(PATH_EDIT_CLIPS), extension);
  967. }
  968. CString savePath = startingFilePath;
  969. //for new files make a unique file name
  970. if (id < 0 &&
  971. FileExists(startingFilePath))
  972. {
  973. savePath = _T("");
  974. for (int y = lastFileCheckId; y < 1000000; y++)
  975. {
  976. CString testFilePath = StrF(_T("%sNewClip_%d.%s"), CGetSetOptions::GetPath(PATH_EDIT_CLIPS), y, extension);
  977. if (FileExists(testFilePath) == FALSE)
  978. {
  979. savePath = testFilePath;
  980. lastFileCheckId = y + 1;
  981. break;
  982. }
  983. }
  984. }
  985. m_editThread.WatchFile(savePath);
  986. clip.WriteTextToFile(savePath, unicodeFile, asciFile, rtfFile, (id == -1));
  987. SHELLEXECUTEINFO sei = { sizeof(sei) };
  988. sei.fMask = SEE_MASK_NOCLOSEPROCESS;
  989. sei.lpVerb = _T("open");
  990. if (exePath != _T(""))
  991. {
  992. sei.lpFile = exePath;
  993. sei.lpParameters = savePath;
  994. Log(StrF(_T("Launching editor path: %s, file: %s"), exePath, savePath));
  995. }
  996. else
  997. {
  998. sei.lpFile = savePath;
  999. Log(StrF(_T("Launching editor without specific exe path, file: %s"), savePath));
  1000. }
  1001. sei.nShow = SW_NORMAL;
  1002. if (ShellExecuteEx(&sei) == FALSE)
  1003. {
  1004. Log(StrF(_T("ShellExecuteEx failed, not editing clipid: %d"), id));
  1005. continue;
  1006. }
  1007. /*DWORD PID = GetProcessId(sei.hProcess);
  1008. HANDLE hProcess = sei.hProcess;
  1009. if (m_editThread.IsRunning() == false)
  1010. {
  1011. m_editThread.SubscribeToFileChanges();
  1012. m_editThread.Start();
  1013. }
  1014. m_editThread.WatchFileForChange(savePath, id, hProcess);*/
  1015. ret = true;
  1016. }
  1017. return true;
  1018. }
  1019. void CCP_MainApp::PumpMessageEx(HWND hWnd)
  1020. {
  1021. MSG KeyboardMsg;
  1022. while (::PeekMessage(&KeyboardMsg, hWnd, 0, 0, PM_REMOVE))
  1023. {
  1024. ::TranslateMessage(&KeyboardMsg);
  1025. ::DispatchMessage(&KeyboardMsg);
  1026. }
  1027. }
  1028. HWND CCP_MainApp::QPastehWnd()
  1029. {
  1030. if(m_pMainFrame != NULL)
  1031. {
  1032. if(m_pMainFrame->m_quickPaste.m_pwndPaste != NULL)
  1033. {
  1034. return m_pMainFrame->m_quickPaste.m_pwndPaste->GetSafeHwnd();
  1035. }
  1036. }
  1037. return NULL;
  1038. }
  1039. CQPasteWnd* CCP_MainApp::QPasteWnd()
  1040. {
  1041. if(m_pMainFrame != NULL)
  1042. {
  1043. return m_pMainFrame->m_quickPaste.m_pwndPaste;
  1044. }
  1045. return NULL;
  1046. }
  1047. bool CCP_MainApp::UACPaste()
  1048. {
  1049. if(m_pUacPasteThread == NULL)
  1050. {
  1051. m_pUacPasteThread = new CUAC_Thread(GetCurrentProcessId());
  1052. }
  1053. return m_pUacPasteThread->UACPaste();
  1054. }
  1055. bool CCP_MainApp::UACCopy()
  1056. {
  1057. if(m_pUacPasteThread == NULL)
  1058. {
  1059. m_pUacPasteThread = new CUAC_Thread(GetCurrentProcessId());
  1060. }
  1061. return m_pUacPasteThread->UACCopy();
  1062. }
  1063. bool CCP_MainApp::UACCut()
  1064. {
  1065. if(m_pUacPasteThread == NULL)
  1066. {
  1067. m_pUacPasteThread = new CUAC_Thread(GetCurrentProcessId());
  1068. }
  1069. return m_pUacPasteThread->UACCut();
  1070. }
  1071. bool CCP_MainApp::UACThreadRunning()
  1072. {
  1073. if(m_pUacPasteThread != NULL)
  1074. {
  1075. return m_pUacPasteThread->IsRunning();
  1076. }
  1077. return false;
  1078. }
  1079. void CCP_MainApp::RefreshShowInTaskBar()
  1080. {
  1081. if(m_pMainFrame != NULL)
  1082. {
  1083. m_pMainFrame->RefreshShowInTaskBar();
  1084. }
  1085. }
  1086. void CCP_MainApp::SetActiveGroupId(int groupId)
  1087. {
  1088. m_activeGroupId = groupId;
  1089. m_activeGroupStartTime = GetTickCount();
  1090. }
  1091. int CCP_MainApp::GetActiveGroupId()
  1092. {
  1093. int ret = -1;
  1094. DWORD maxDiff = CGetSetOptions::GetSaveToGroupTimeoutMS();
  1095. DWORD diff = GetTickCount() - m_activeGroupStartTime;
  1096. if(m_activeGroupId > -1 &&
  1097. diff < maxDiff)
  1098. {
  1099. ret = m_activeGroupId;
  1100. }
  1101. m_activeGroupId = -1;
  1102. m_activeGroupStartTime = 0;
  1103. return ret;
  1104. }
  1105. void CCP_MainApp::SetCopyReason(CopyReasonEnum::CopyReason copyReason)
  1106. {
  1107. m_copyReason = copyReason;
  1108. m_copyReasonStartTime = GetTickCount();
  1109. }
  1110. CopyReasonEnum::CopyReason CCP_MainApp::GetCopyReason()
  1111. {
  1112. CopyReasonEnum::CopyReason ret = CopyReasonEnum::COPY_TO_UNKOWN;
  1113. DWORD maxDiff = CGetSetOptions::GetCopyReasonTimeoutMS();
  1114. DWORD diff = GetTickCount() - m_copyReasonStartTime;
  1115. if(m_copyReason != CopyReasonEnum::COPY_TO_UNKOWN &&
  1116. diff < maxDiff)
  1117. {
  1118. ret = m_copyReason;
  1119. }
  1120. m_copyReason = CopyReasonEnum::COPY_TO_UNKOWN;
  1121. m_copyReasonStartTime = 0;
  1122. return ret;
  1123. }