Misc.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489
  1. #include "stdafx.h"
  2. #include "CP_Main.h"
  3. #include "Misc.h"
  4. #include "OptionsSheet.h"
  5. #include "shared/TextConvert.h"
  6. #include "AlphaBlend.h"
  7. #include "Tlhelp32.h"
  8. #include <Wininet.h>
  9. #include "sqlite\utext.h"
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include "Path.h"
  13. CString GetIPAddress()
  14. {
  15. WORD wVersionRequested;
  16. WSADATA wsaData;
  17. char name[255];
  18. CString IP;
  19. PHOSTENT hostinfo;
  20. wVersionRequested = MAKEWORD(2,0);
  21. if (WSAStartup(wVersionRequested, &wsaData)==0)
  22. {
  23. if(gethostname(name, sizeof(name))==0)
  24. {
  25. if((hostinfo=gethostbyname(name)) != NULL)
  26. {
  27. IP = inet_ntoa(*(struct in_addr*)* hostinfo->h_addr_list);
  28. }
  29. }
  30. WSACleanup();
  31. }
  32. IP.MakeUpper();
  33. return IP;
  34. }
  35. CString GetComputerName()
  36. {
  37. TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1] = _T("");
  38. DWORD Size=MAX_COMPUTERNAME_LENGTH+1;
  39. GetComputerName(ComputerName, &Size);
  40. CString cs(ComputerName);
  41. cs.MakeUpper();
  42. return cs;
  43. }
  44. void AppendToFile(const TCHAR* fn, const TCHAR* msg)
  45. {
  46. #ifdef _UNICODE
  47. FILE *file = _wfopen(fn, _T("a"));
  48. #else
  49. FILE *file = fopen(fn, _T("a"));
  50. #endif
  51. ASSERT( file );
  52. if(file != NULL)
  53. {
  54. #ifdef _UNICODE
  55. fwprintf(file, _T("%s"), msg);
  56. #else
  57. fprintf(file, _T("%s"),msg);
  58. #endif
  59. fclose(file);
  60. }
  61. }
  62. void log(const TCHAR* msg, bool bFromSendRecieve, CString csFile, long lLine)
  63. {
  64. ASSERT(AfxIsValidString(msg));
  65. SYSTEMTIME st;
  66. GetLocalTime(&st);
  67. CString csText;
  68. csText.Format(_T("[%d/%d/%d %02d:%02d:%02d.%03d - "), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  69. CString csFileLine;
  70. csFile = GetFileName(csFile);
  71. csFileLine.Format(_T("%s %d] "), csFile, lLine);
  72. csText += csFileLine;
  73. csText += msg;
  74. csText += "\n";
  75. #ifndef _DEBUG
  76. if(CGetSetOptions::m_bOutputDebugString)
  77. #endif
  78. {
  79. OutputDebugString(csText);
  80. }
  81. #ifndef _DEBUG
  82. if(!bFromSendRecieve)
  83. {
  84. if(!g_Opt.m_bEnableDebugLogging)
  85. return;
  86. }
  87. #endif
  88. CString csExeFile = CGetSetOptions::GetPath(PATH_LOG_FILE);
  89. csExeFile += "Ditto.log";
  90. AppendToFile(csExeFile, csText);
  91. }
  92. void logsendrecieveinfo(CString cs, CString csFile, long lLine)
  93. {
  94. if(g_Opt.m_bLogSendReceiveErrors)
  95. log(cs, true, csFile, lLine);
  96. }
  97. CString GetErrorString( int err )
  98. {
  99. CString str;
  100. LPVOID lpMsgBuf;
  101. ::FormatMessage(
  102. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  103. NULL,
  104. err,
  105. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  106. (LPTSTR) &lpMsgBuf,
  107. 0,
  108. NULL
  109. );
  110. str = (LPCTSTR) lpMsgBuf;
  111. // Display the string.
  112. // ::MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
  113. ::LocalFree( lpMsgBuf );
  114. return str;
  115. }
  116. int g_funnyGetTickCountAdjustment = -1;
  117. double IdleSeconds()
  118. {
  119. LASTINPUTINFO info;
  120. info.cbSize = sizeof(info);
  121. GetLastInputInfo(&info);
  122. DWORD currentTick = GetTickCount();
  123. if(g_funnyGetTickCountAdjustment == -1)
  124. {
  125. if(currentTick < info.dwTime)
  126. {
  127. g_funnyGetTickCountAdjustment = 1;
  128. }
  129. else
  130. {
  131. g_funnyGetTickCountAdjustment = 0;
  132. }
  133. }
  134. if(g_funnyGetTickCountAdjustment == 1 || g_funnyGetTickCountAdjustment == 2)
  135. {
  136. //Output message the first time
  137. if(g_funnyGetTickCountAdjustment == 1)
  138. {
  139. Log(StrF(_T("Adjusting time of get tickcount by: %d, on startup we found GetTickCount to be less than last input"), CGetSetOptions::GetFunnyTickCountAdjustment()));
  140. g_funnyGetTickCountAdjustment = 2;
  141. }
  142. currentTick += CGetSetOptions::GetFunnyTickCountAdjustment();
  143. }
  144. double idleSeconds = (currentTick - info.dwTime)/1000.0;
  145. return idleSeconds;
  146. }
  147. CString StrF(const TCHAR * pszFormat, ...)
  148. {
  149. ASSERT( AfxIsValidString( pszFormat ) );
  150. CString str;
  151. va_list argList;
  152. va_start( argList, pszFormat );
  153. str.FormatV( pszFormat, argList );
  154. va_end( argList );
  155. return str;
  156. }
  157. BYTE GetEscapeChar( BYTE ch )
  158. {
  159. switch(ch)
  160. {
  161. case '\'': return '\''; // Single quotation mark (') = 39 or 0x27
  162. case '\"': return '\"'; // Double quotation mark (") = 34 or 0x22
  163. case '?': return '\?'; // Question mark (?) = 63 or 0x3f
  164. case '\\': return '\\'; // Backslash (\) = 92 or 0x5c
  165. case 'a': return '\a'; // Alert (BEL) = 7
  166. case 'b': return '\b'; // Backspace (BS) = 8
  167. case 'f': return '\f'; // Formfeed (FF) = 12 or 0x0c
  168. case 'n': return '\n'; // Newline (NL or LF) = 10 or 0x0a
  169. case 'r': return '\r'; // Carriage Return (CR) = 13 or 0x0d
  170. case 't': return '\t'; // Horizontal tab (HT) = 9
  171. case 'v': return '\v'; // Vertical tab (VT) = 11 or 0x0b
  172. case '0': return '\0'; // Null character (NUL) = 0
  173. }
  174. return 0; // invalid
  175. }
  176. CString RemoveEscapes( const TCHAR* str )
  177. {
  178. ASSERT( str );
  179. CString ret;
  180. TCHAR* pSrc = (TCHAR*) str;
  181. TCHAR* pDest = ret.GetBuffer((int)STRLEN(pSrc));
  182. TCHAR* pStart = pDest;
  183. while( *pSrc != '\0' )
  184. {
  185. if( *pSrc == '\\' )
  186. {
  187. pSrc++;
  188. *pDest = GetEscapeChar((BYTE)pSrc );
  189. }
  190. else
  191. *pDest = *pSrc;
  192. pSrc++;
  193. pDest++;
  194. }
  195. ret.ReleaseBuffer((int)(pDest - pStart));
  196. return ret;
  197. }
  198. CString GetWndText( HWND hWnd )
  199. {
  200. CString text;
  201. if( !IsWindow(hWnd) )
  202. return "! NOT A VALID WINDOW !";
  203. CWnd* pWnd = CWnd::FromHandle(hWnd);
  204. pWnd->GetWindowText(text);
  205. return text;
  206. }
  207. bool IsAppWnd( HWND hWnd )
  208. {
  209. DWORD dwMyPID = ::GetCurrentProcessId();
  210. DWORD dwTestPID;
  211. ::GetWindowThreadProcessId( hWnd, &dwTestPID );
  212. return dwMyPID == dwTestPID;
  213. }
  214. /*----------------------------------------------------------------------------*\
  215. Global Memory Helper Functions
  216. \*----------------------------------------------------------------------------*/
  217. // make sure the given HGLOBAL is valid.
  218. BOOL IsValid(HGLOBAL hGlobal)
  219. {
  220. void* pvData = ::GlobalLock(hGlobal);
  221. ::GlobalUnlock(hGlobal);
  222. return (pvData != NULL);
  223. }
  224. // asserts if hDest isn't big enough
  225. void CopyToGlobalHP(HGLOBAL hDest, LPVOID pBuf, SIZE_T ulBufLen)
  226. {
  227. ASSERT(hDest && pBuf && ulBufLen);
  228. LPVOID pvData = GlobalLock(hDest);
  229. ASSERT(pvData);
  230. SIZE_T size = GlobalSize(hDest);
  231. ASSERT(size >= ulBufLen); // assert if hDest isn't big enough
  232. memcpy(pvData, pBuf, ulBufLen);
  233. GlobalUnlock(hDest);
  234. }
  235. void CopyToGlobalHH(HGLOBAL hDest, HGLOBAL hSource, SIZE_T ulBufLen)
  236. {
  237. ASSERT(hDest && hSource && ulBufLen);
  238. LPVOID pvData = GlobalLock(hSource);
  239. ASSERT(pvData );
  240. SIZE_T size = GlobalSize(hSource);
  241. ASSERT(size >= ulBufLen); // assert if hSource isn't big enough
  242. CopyToGlobalHP(hDest, pvData, ulBufLen);
  243. GlobalUnlock(hSource);
  244. }
  245. HGLOBAL NewGlobalP(LPVOID pBuf, SIZE_T nLen)
  246. {
  247. ASSERT(pBuf && nLen);
  248. HGLOBAL hDest = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, nLen);
  249. ASSERT(hDest );
  250. CopyToGlobalHP(hDest, pBuf, nLen);
  251. return hDest;
  252. }
  253. HGLOBAL NewGlobal(SIZE_T nLen)
  254. {
  255. ASSERT(nLen);
  256. HGLOBAL hDest = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, nLen);
  257. return hDest;
  258. }
  259. HGLOBAL NewGlobalH(HGLOBAL hSource, SIZE_T nLen)
  260. {
  261. ASSERT(hSource && nLen);
  262. LPVOID pvData = GlobalLock(hSource);
  263. HGLOBAL hDest = NewGlobalP(pvData, nLen);
  264. GlobalUnlock(hSource);
  265. return hDest;
  266. }
  267. int CompareGlobalHP(HGLOBAL hLeft, LPVOID pBuf, SIZE_T ulBufLen)
  268. {
  269. ASSERT(hLeft && pBuf && ulBufLen);
  270. LPVOID pvData = GlobalLock(hLeft);
  271. ASSERT(pvData);
  272. ASSERT(ulBufLen <= GlobalSize(hLeft));
  273. int result = memcmp(pvData, pBuf, ulBufLen);
  274. GlobalUnlock(hLeft);
  275. return result;
  276. }
  277. int CompareGlobalHH( HGLOBAL hLeft, HGLOBAL hRight, SIZE_T ulBufLen)
  278. {
  279. ASSERT(hLeft && hRight && ulBufLen);
  280. ASSERT(ulBufLen <= GlobalSize(hRight));
  281. LPVOID pvData = GlobalLock(hRight);
  282. ASSERT(pvData);
  283. int result = CompareGlobalHP(hLeft, pvData, ulBufLen);
  284. GlobalUnlock(hLeft);
  285. return result;
  286. }
  287. //Do not change these these are stored in the database
  288. CLIPFORMAT GetFormatID(LPCTSTR cbName)
  289. {
  290. if(STRCMP(cbName, _T("CF_TEXT")) == 0)
  291. return CF_TEXT;
  292. else if(STRCMP(cbName, _T("CF_METAFILEPICT")) == 0)
  293. return CF_METAFILEPICT;
  294. else if(STRCMP(cbName, _T("CF_SYLK")) == 0)
  295. return CF_SYLK;
  296. else if(STRCMP(cbName, _T("CF_DIF")) == 0)
  297. return CF_DIF;
  298. else if(STRCMP(cbName, _T("CF_TIFF")) == 0)
  299. return CF_TIFF;
  300. else if(STRCMP(cbName, _T("CF_OEMTEXT")) == 0)
  301. return CF_OEMTEXT;
  302. else if(STRCMP(cbName, _T("CF_DIB")) == 0)
  303. return CF_DIB;
  304. else if(STRCMP(cbName, _T("CF_PALETTE")) == 0)
  305. return CF_PALETTE;
  306. else if(STRCMP(cbName, _T("CF_PENDATA")) == 0)
  307. return CF_PENDATA;
  308. else if(STRCMP(cbName, _T("CF_RIFF")) == 0)
  309. return CF_RIFF;
  310. else if(STRCMP(cbName, _T("CF_WAVE")) == 0)
  311. return CF_WAVE;
  312. else if(STRCMP(cbName, _T("CF_UNICODETEXT")) == 0)
  313. return CF_UNICODETEXT;
  314. else if(STRCMP(cbName, _T("CF_ENHMETAFILE")) == 0)
  315. return CF_ENHMETAFILE;
  316. else if(STRCMP(cbName, _T("CF_HDROP")) == 0)
  317. return CF_HDROP;
  318. else if(STRCMP(cbName, _T("CF_LOCALE")) == 0)
  319. return CF_LOCALE;
  320. else if(STRCMP(cbName, _T("CF_OWNERDISPLAY")) == 0)
  321. return CF_OWNERDISPLAY;
  322. else if(STRCMP(cbName, _T("CF_DSPTEXT")) == 0)
  323. return CF_DSPTEXT;
  324. else if(STRCMP(cbName, _T("CF_DSPBITMAP")) == 0)
  325. return CF_DSPBITMAP;
  326. else if(STRCMP(cbName, _T("CF_DSPMETAFILEPICT")) == 0)
  327. return CF_DSPMETAFILEPICT;
  328. else if(STRCMP(cbName, _T("CF_DSPENHMETAFILE")) == 0)
  329. return CF_DSPENHMETAFILE;
  330. return ::RegisterClipboardFormat(cbName);
  331. }
  332. //Do not change these these are stored in the database
  333. CString GetFormatName(CLIPFORMAT cbType)
  334. {
  335. switch(cbType)
  336. {
  337. case CF_TEXT:
  338. return _T("CF_TEXT");
  339. case CF_BITMAP:
  340. return _T("CF_BITMAP");
  341. case CF_METAFILEPICT:
  342. return _T("CF_METAFILEPICT");
  343. case CF_SYLK:
  344. return _T("CF_SYLK");
  345. case CF_DIF:
  346. return _T("CF_DIF");
  347. case CF_TIFF:
  348. return _T("CF_TIFF");
  349. case CF_OEMTEXT:
  350. return _T("CF_OEMTEXT");
  351. case CF_DIB:
  352. return _T("CF_DIB");
  353. case CF_PALETTE:
  354. return _T("CF_PALETTE");
  355. case CF_PENDATA:
  356. return _T("CF_PENDATA");
  357. case CF_RIFF:
  358. return _T("CF_RIFF");
  359. case CF_WAVE:
  360. return _T("CF_WAVE");
  361. case CF_UNICODETEXT:
  362. return _T("CF_UNICODETEXT");
  363. case CF_ENHMETAFILE:
  364. return _T("CF_ENHMETAFILE");
  365. case CF_HDROP:
  366. return _T("CF_HDROP");
  367. case CF_LOCALE:
  368. return _T("CF_LOCALE");
  369. case CF_OWNERDISPLAY:
  370. return _T("CF_OWNERDISPLAY");
  371. case CF_DSPTEXT:
  372. return _T("CF_DSPTEXT");
  373. case CF_DSPBITMAP:
  374. return _T("CF_DSPBITMAP");
  375. case CF_DSPMETAFILEPICT:
  376. return _T("CF_DSPMETAFILEPICT");
  377. case CF_DSPENHMETAFILE:
  378. return _T("CF_DSPENHMETAFILE");
  379. default:
  380. //Not a default type get the name from the clipboard
  381. if (cbType != 0)
  382. {
  383. TCHAR szFormat[256];
  384. GetClipboardFormatName(cbType, szFormat, 256);
  385. return szFormat;
  386. }
  387. break;
  388. }
  389. return "ERROR";
  390. }
  391. CString GetFilePath(CString csFileName)
  392. {
  393. long lSlash = csFileName.ReverseFind('\\');
  394. if(lSlash > -1)
  395. {
  396. csFileName = csFileName.Left(lSlash + 1);
  397. }
  398. return csFileName;
  399. }
  400. CString GetFileName(CString csFileName)
  401. {
  402. long lSlash = csFileName.ReverseFind('\\');
  403. if(lSlash > -1)
  404. {
  405. csFileName = csFileName.Right(csFileName.GetLength() - lSlash - 1);
  406. }
  407. return csFileName;
  408. }
  409. /****************************************************************************************************
  410. BOOL CALLBACK MyMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  411. ***************************************************************************************************/
  412. typedef struct
  413. {
  414. long lFlags; // Flags
  415. LPRECT pVirtualRect; // Ptr to rect that receives the results, or the src of the monitor search method
  416. int iMonitor; // Ndx to the mointor to look at, -1 for all, -or- result of the monitor search method
  417. int nMonitorCount; // Total number of monitors found, -1 for monitor search method
  418. } MONITOR_ENUM_PARAM;
  419. #define MONITOR_SEARCH_METOHD 0x00000001
  420. BOOL CALLBACK MyMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  421. {
  422. // Typecast param
  423. MONITOR_ENUM_PARAM* pParam = (MONITOR_ENUM_PARAM*)dwData;
  424. if(pParam)
  425. {
  426. // If a dest rect was passed
  427. if(pParam->pVirtualRect)
  428. {
  429. // If MONITOR_SEARCH_METOHD then we are being asked for the index of the monitor
  430. // that the rect falls inside of
  431. if(pParam->lFlags & MONITOR_SEARCH_METOHD)
  432. {
  433. if( (pParam->pVirtualRect->right < lprcMonitor->left) ||
  434. (pParam->pVirtualRect->left > lprcMonitor->right) ||
  435. (pParam->pVirtualRect->bottom < lprcMonitor->top) ||
  436. (pParam->pVirtualRect->top > lprcMonitor->bottom))
  437. {
  438. // Nothing
  439. }
  440. else
  441. {
  442. // This is the one
  443. pParam->iMonitor = pParam->nMonitorCount;
  444. // Stop the enumeration
  445. return FALSE;
  446. }
  447. }
  448. else
  449. {
  450. if(pParam->iMonitor == pParam->nMonitorCount)
  451. {
  452. *pParam->pVirtualRect = *lprcMonitor;
  453. }
  454. else
  455. if(pParam->iMonitor == -1)
  456. {
  457. pParam->pVirtualRect->left = min(pParam->pVirtualRect->left, lprcMonitor->left);
  458. pParam->pVirtualRect->top = min(pParam->pVirtualRect->top, lprcMonitor->top);
  459. pParam->pVirtualRect->right = max(pParam->pVirtualRect->right, lprcMonitor->right);
  460. pParam->pVirtualRect->bottom = max(pParam->pVirtualRect->bottom, lprcMonitor->bottom);
  461. }
  462. }
  463. }
  464. // Up the count if necessary
  465. pParam->nMonitorCount++;
  466. }
  467. return TRUE;
  468. }
  469. int GetScreenWidth(void)
  470. {
  471. OSVERSIONINFO OS_Version_Info;
  472. DWORD dwPlatform = 0;
  473. if(GetVersionEx(&OS_Version_Info) != 0)
  474. {
  475. dwPlatform = OS_Version_Info.dwPlatformId;
  476. }
  477. if(dwPlatform == VER_PLATFORM_WIN32_NT)
  478. {
  479. int width, height;
  480. width = GetSystemMetrics(SM_CXSCREEN);
  481. height = GetSystemMetrics(SM_CYSCREEN);
  482. switch(width)
  483. {
  484. default:
  485. case 640:
  486. case 800:
  487. case 1024:
  488. return(width);
  489. case 1280:
  490. if(height == 480)
  491. {
  492. return(width / 2);
  493. }
  494. return(width);
  495. case 1600:
  496. if(height == 600)
  497. {
  498. return(width / 2);
  499. }
  500. return(width);
  501. case 2048:
  502. if(height == 768)
  503. {
  504. return(width / 2);
  505. }
  506. return(width);
  507. }
  508. }
  509. else
  510. {
  511. return(GetSystemMetrics(SM_CXVIRTUALSCREEN));
  512. }
  513. }
  514. int GetScreenHeight(void)
  515. {
  516. OSVERSIONINFO OS_Version_Info;
  517. DWORD dwPlatform = 0;
  518. if(GetVersionEx(&OS_Version_Info) != 0)
  519. {
  520. dwPlatform = OS_Version_Info.dwPlatformId;
  521. }
  522. if(dwPlatform == VER_PLATFORM_WIN32_NT)
  523. {
  524. int width, height;
  525. width = GetSystemMetrics(SM_CXSCREEN);
  526. height = GetSystemMetrics(SM_CYSCREEN);
  527. switch(height)
  528. {
  529. default:
  530. case 480:
  531. case 600:
  532. case 768:
  533. return(height);
  534. case 960:
  535. if(width == 640)
  536. {
  537. return(height / 2);
  538. }
  539. return(height);
  540. case 1200:
  541. if(width == 800)
  542. {
  543. return(height / 2);
  544. }
  545. return(height);
  546. case 1536:
  547. if(width == 1024)
  548. {
  549. return(height / 2);
  550. }
  551. return(height);
  552. }
  553. }
  554. else
  555. {
  556. return(GetSystemMetrics(SM_CYVIRTUALSCREEN));
  557. }
  558. }
  559. /*------------------------------------------------------------------*\
  560. ID based Globals
  561. \*------------------------------------------------------------------*/
  562. long NewGroupID(int parentID, CString text)
  563. {
  564. long lID=0;
  565. CTime time;
  566. time = CTime::GetCurrentTime();
  567. try
  568. {
  569. //sqlite doesn't like single quotes ' replace them with double ''
  570. if(text.IsEmpty())
  571. text = time.Format("NewGroup %y/%m/%d %H:%M:%S");
  572. text.Replace(_T("'"), _T("''"));
  573. CString cs;
  574. cs.Format(_T("insert into Main (lDate, mText, lDontAutoDelete, bIsGroup, lParentID, stickyClipOrder, stickyClipGroupOrder) values(%d, '%s', %d, 1, %d, -(2147483647), -(2147483647));"),
  575. (int)time.GetTime(),
  576. text,
  577. (int)time.GetTime(),
  578. parentID);
  579. theApp.m_db.execDML(cs);
  580. lID = (long)theApp.m_db.lastRowId();
  581. }
  582. CATCH_SQLITE_EXCEPTION_AND_RETURN(0)
  583. return lID;
  584. }
  585. BOOL DeleteAllIDs()
  586. {
  587. try
  588. {
  589. theApp.m_db.execDML(_T("DELETE FROM Data;"));
  590. theApp.m_db.execDML(_T("DELETE FROM Main;"));
  591. }
  592. CATCH_SQLITE_EXCEPTION
  593. return TRUE;
  594. }
  595. BOOL DeleteFormats(int parentID, ARRAY& formatIDs)
  596. {
  597. if(formatIDs.GetSize() <= 0)
  598. return TRUE;
  599. try
  600. {
  601. //Delete the requested data formats
  602. INT_PTR count = formatIDs.GetSize();
  603. for(int i = 0; i < count; i++)
  604. {
  605. int count = theApp.m_db.execDMLEx(_T("DELETE FROM Data WHERE lID = %d;"), formatIDs[i]);
  606. int k = 0;
  607. }
  608. CClip clip;
  609. if(clip.LoadFormats(parentID))
  610. {
  611. DWORD CRC = clip.GenerateCRC();
  612. //Update the main table with new size
  613. theApp.m_db.execDMLEx(_T("UPDATE Main SET CRC = %d WHERE lID = %d"), CRC, parentID);
  614. }
  615. }
  616. CATCH_SQLITE_EXCEPTION
  617. return TRUE;
  618. }
  619. CRect CenterRect(CRect startingRect)
  620. {
  621. CRect crMonitor;
  622. HMONITOR monitorHandle = MonitorFromPoint(startingRect.TopLeft(), MONITOR_DEFAULTTONEAREST);
  623. if (monitorHandle == NULL)
  624. {
  625. monitorHandle = MonitorFromPoint(startingRect.TopLeft(), MONITOR_DEFAULTTOPRIMARY);
  626. MONITORINFO lpmi;
  627. lpmi.cbSize = sizeof(MONITORINFO);
  628. if (GetMonitorInfo(monitorHandle, &lpmi))
  629. {
  630. crMonitor.CopyRect(&lpmi.rcWork);
  631. }
  632. }
  633. else
  634. {
  635. MONITORINFO lpmi;
  636. lpmi.cbSize = sizeof(MONITORINFO);
  637. if (GetMonitorInfo(monitorHandle, &lpmi))
  638. {
  639. crMonitor.CopyRect(&lpmi.rcWork);
  640. }
  641. }
  642. return CenterRectFromRect(startingRect, crMonitor);
  643. }
  644. CRect CenterRectFromRect(CRect startingRect, CRect outerRect)
  645. {
  646. CPoint center = outerRect.CenterPoint();
  647. CRect centerRect;
  648. centerRect.left = center.x - (startingRect.Width() / 2);
  649. centerRect.top = center.y - (startingRect.Height() / 2);
  650. centerRect.right = centerRect.left + startingRect.Width();
  651. centerRect.bottom = centerRect.top + startingRect.Height();
  652. return centerRect;
  653. }
  654. CRect DefaultMonitorRect()
  655. {
  656. CRect crMonitor;
  657. CRect invalidRect(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
  658. HMONITOR monitorHandle = MonitorFromPoint(invalidRect.TopLeft(), MONITOR_DEFAULTTOPRIMARY);
  659. MONITORINFO lpmi;
  660. lpmi.cbSize = sizeof(MONITORINFO);
  661. if (GetMonitorInfo(monitorHandle, &lpmi))
  662. {
  663. crMonitor.CopyRect(&lpmi.rcWork);
  664. }
  665. return crMonitor;
  666. }
  667. CRect MonitorRectFromRect(CRect rect)
  668. {
  669. BOOL ret = FALSE;
  670. CRect crMonitor;
  671. HMONITOR monitorHandle = MonitorFromPoint(rect.TopLeft(), MONITOR_DEFAULTTONEAREST);
  672. if (monitorHandle == NULL)
  673. {
  674. monitorHandle = MonitorFromPoint(rect.TopLeft(), MONITOR_DEFAULTTOPRIMARY);
  675. MONITORINFO lpmi;
  676. lpmi.cbSize = sizeof(MONITORINFO);
  677. if (GetMonitorInfo(monitorHandle, &lpmi))
  678. {
  679. crMonitor.CopyRect(&lpmi.rcWork);
  680. }
  681. }
  682. else
  683. {
  684. MONITORINFO lpmi;
  685. lpmi.cbSize = sizeof(MONITORINFO);
  686. if (GetMonitorInfo(monitorHandle, &lpmi))
  687. {
  688. crMonitor.CopyRect(&lpmi.rcWork);
  689. }
  690. }
  691. return crMonitor;
  692. }
  693. BOOL EnsureWindowVisible(CRect *pcrRect)
  694. {
  695. BOOL ret = FALSE;
  696. CRect crMonitor;
  697. CDPI dpi;
  698. HMONITOR monitorHandle = MonitorFromRect(pcrRect, MONITOR_DEFAULTTONEAREST);
  699. if (monitorHandle == NULL)
  700. {
  701. monitorHandle = MonitorFromRect(pcrRect, MONITOR_DEFAULTTOPRIMARY);
  702. MONITORINFO lpmi;
  703. lpmi.cbSize = sizeof(MONITORINFO);
  704. if (GetMonitorInfo(monitorHandle, &lpmi))
  705. {
  706. crMonitor.CopyRect(&lpmi.rcWork);
  707. *pcrRect = CenterRectFromRect(*pcrRect, crMonitor);
  708. }
  709. }
  710. else
  711. {
  712. MONITORINFO lpmi;
  713. lpmi.cbSize = sizeof(MONITORINFO);
  714. if (GetMonitorInfo(monitorHandle, &lpmi))
  715. {
  716. crMonitor.CopyRect(&lpmi.rcWork);
  717. }
  718. }
  719. bool movedLeft = false;
  720. //Validate the left
  721. long lDiff = pcrRect->left - crMonitor.left;
  722. if (lDiff < 0)
  723. {
  724. pcrRect->left += abs(lDiff);
  725. pcrRect->right += abs(lDiff);
  726. ret = TRUE;
  727. movedLeft = true;
  728. }
  729. //Right side
  730. lDiff = pcrRect->right - crMonitor.right;
  731. if (lDiff > 0)
  732. {
  733. if (movedLeft == false)
  734. {
  735. pcrRect->left -= abs(lDiff);
  736. }
  737. pcrRect->right -= abs(lDiff);
  738. ret = TRUE;
  739. }
  740. bool movedTop = false;
  741. //Top
  742. lDiff = pcrRect->top - crMonitor.top;
  743. if (lDiff < 0)
  744. {
  745. pcrRect->top += abs(lDiff);
  746. pcrRect->bottom += abs(lDiff);
  747. ret = TRUE;
  748. movedTop = true;
  749. }
  750. //Bottom
  751. lDiff = pcrRect->bottom - crMonitor.bottom;
  752. if (lDiff > 0)
  753. {
  754. if (movedTop == false)
  755. {
  756. pcrRect->top -= abs(lDiff);
  757. }
  758. pcrRect->bottom -= abs(lDiff);
  759. ret = TRUE;
  760. }
  761. return ret;
  762. }
  763. __int64 GetLastWriteTime(const CString &csFile)
  764. {
  765. __int64 nLastWrite = 0;
  766. CFileFind finder;
  767. BOOL bResult = finder.FindFile(csFile);
  768. if (bResult)
  769. {
  770. finder.FindNextFile();
  771. FILETIME ft;
  772. finder.GetLastWriteTime(&ft);
  773. memcpy(&nLastWrite, &ft, sizeof(ft));
  774. }
  775. return nLastWrite;
  776. }
  777. typedef struct
  778. {
  779. DWORD ownerpid;
  780. DWORD childpid;
  781. } windowinfo;
  782. BOOL CALLBACK EnumChildWindowsCallback(HWND hWnd, LPARAM lp)
  783. {
  784. windowinfo* info = (windowinfo*)lp;
  785. DWORD pid = 0;
  786. GetWindowThreadProcessId(hWnd, &pid);
  787. if (pid != info->ownerpid)
  788. info->childpid = pid;
  789. return TRUE;
  790. }
  791. CString UWP_AppName(HWND active_window, DWORD ownerpid)
  792. {
  793. CString uwpAppName;
  794. windowinfo info = { 0 };
  795. info.ownerpid = ownerpid;
  796. info.childpid = info.ownerpid;
  797. EnumChildWindows(active_window, EnumChildWindowsCallback, (LPARAM)&info);
  798. HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info.childpid);
  799. if (active_process != NULL)
  800. {
  801. WCHAR image_name[MAX_PATH] = { 0 };
  802. DWORD bufsize = MAX_PATH;
  803. QueryFullProcessImageName(active_process, 0, image_name, &bufsize);
  804. CloseHandle(active_process);
  805. nsPath::CPath path(image_name);
  806. uwpAppName = path.GetName();
  807. }
  808. return uwpAppName;
  809. }
  810. CString GetProcessName(HWND hWnd, DWORD processId)
  811. {
  812. DWORD startTick = GetTickCount();
  813. CString strProcessName;
  814. DWORD Id = processId;
  815. if (Id == 0)
  816. {
  817. GetWindowThreadProcessId(hWnd, &Id);
  818. }
  819. HANDLE active_process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, Id);
  820. if (active_process != NULL)
  821. {
  822. WCHAR image_name[MAX_PATH] = { 0 };
  823. DWORD bufsize = MAX_PATH;
  824. QueryFullProcessImageName(active_process, 0, image_name, &bufsize);
  825. CloseHandle(active_process);
  826. nsPath::CPath path(image_name);
  827. strProcessName = path.GetName();
  828. }
  829. if (strProcessName == _T(""))
  830. {
  831. Log(StrF(_T("failed to get process name from open process, LastError: %d, looping over process names to find process"), GetLastError()));
  832. PROCESSENTRY32 processEntry = { 0 };
  833. HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  834. processEntry.dwSize = sizeof(PROCESSENTRY32);
  835. if (Process32First(hSnapShot, &processEntry))
  836. {
  837. do
  838. {
  839. if (processEntry.th32ProcessID == Id)
  840. {
  841. strProcessName = processEntry.szExeFile;
  842. break;
  843. }
  844. } while (Process32Next(hSnapShot, &processEntry));
  845. }
  846. CloseHandle(hSnapShot);
  847. }
  848. //uwp apps are wrapped in another app called, if this has focus then try and find the child uwp process
  849. if (strProcessName == _T("ApplicationFrameHost.exe"))
  850. {
  851. strProcessName = UWP_AppName(hWnd, Id);
  852. }
  853. DWORD endTick = GetTickCount();
  854. DWORD diff = endTick - startTick;
  855. if(diff > 5)
  856. {
  857. Log(StrF(_T("GetProcessName Time (ms): %d, pid: %d, name: %s"), endTick-startTick, Id, strProcessName));
  858. }
  859. return strProcessName;
  860. }
  861. BOOL IsVista()
  862. {
  863. OSVERSIONINFO osver;
  864. osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  865. if (::GetVersionEx( &osver ) &&
  866. osver.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  867. (osver.dwMajorVersion >= 6 ) )
  868. {
  869. return TRUE;
  870. }
  871. return FALSE;
  872. }
  873. bool IsRunningLimited()
  874. {
  875. LPCTSTR pszSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
  876. LPCTSTR pszValue = _T("EnableLUA");
  877. DWORD dwType = 0;
  878. DWORD dwValue = 0;
  879. DWORD dwValueSize = sizeof(DWORD);
  880. if(ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, pszSubKey, pszValue, &dwType, &dwValue, &dwValueSize))
  881. {
  882. //failed to read the reg key, either it's not there or we don't have access to the registry
  883. //If we are vista then assume we don't have access and we are running as a limited app
  884. //otherwise we are xp and the reg key probably doesn't exist and we are not a limited running app
  885. if(IsVista())
  886. {
  887. OutputDebugString(_T("Ditto - Failed to read registry entry finding UAC, Running as limited application"));
  888. return true;
  889. }
  890. }
  891. if(dwValue == 1)
  892. {
  893. OutputDebugString(_T("Ditto - UAC ENABLED, Running as limited application"));
  894. return true;
  895. }
  896. OutputDebugString(_T("Ditto - Running as standard application"));
  897. return false;
  898. }
  899. void DeleteDittoTempFiles(BOOL checkFileLastAccess)
  900. {
  901. CString csDir = CGetSetOptions::GetPath(PATH_REMOTE_FILES);
  902. if (FileExists(csDir))
  903. {
  904. DeleteFolderFiles(csDir, checkFileLastAccess);
  905. }
  906. csDir = CGetSetOptions::GetPath(PATH_DRAG_FILES);
  907. if (FileExists(csDir))
  908. {
  909. DeleteFolderFiles(csDir, checkFileLastAccess);
  910. }
  911. csDir = CGetSetOptions::GetPath(PATH_CLIP_DIFF);
  912. if (FileExists(csDir))
  913. {
  914. DeleteFolderFiles(csDir, checkFileLastAccess);
  915. }
  916. }
  917. void DeleteFolderFiles(CString csDir, BOOL checkFileLastAccess)
  918. {
  919. if (csDir.Find(_T("\\ReceivedFiles\\")) == -1 && csDir.Find(_T("\\DragFiles\\")) == -1 && csDir.Find(_T("ClipCompare")) == -1)
  920. return;
  921. Log(StrF(_T("Deleting files in Folder %s Check Last Access %d"), csDir, checkFileLastAccess));
  922. FIX_CSTRING_PATH(csDir);
  923. CTime ctOld = CTime::GetCurrentTime();
  924. CTime ctFile;
  925. ctOld -= CTimeSpan(0, 0, 0, 1);
  926. CFileFind Find;
  927. CString csFindString;
  928. csFindString.Format(_T("%s*.*"), csDir);
  929. BOOL bFound = Find.FindFile(csFindString);
  930. while(bFound)
  931. {
  932. bFound = Find.FindNextFile();
  933. if(Find.IsDots())
  934. continue;
  935. if(Find.IsDirectory())
  936. {
  937. CString csDir(Find.GetFilePath());
  938. DeleteFolderFiles(csDir, checkFileLastAccess);
  939. RemoveDirectory(csDir);
  940. }
  941. if(checkFileLastAccess &&
  942. Find.GetLastAccessTime(ctFile))
  943. {
  944. //Delete the remote copied file if it hasn't been used for the last day
  945. if(ctFile < ctOld)
  946. {
  947. Log(StrF(_T("Deleting temp file %s"), Find.GetFilePath()));
  948. DeleteFile(Find.GetFilePath());
  949. }
  950. }
  951. else
  952. {
  953. Log(StrF(_T("Deleting temp file %s"), Find.GetFilePath()));
  954. DeleteFile(Find.GetFilePath());
  955. }
  956. }
  957. }
  958. __int64 FileSize(const TCHAR *fileName)
  959. {
  960. struct _stat64 buf;
  961. if (_wstat64((wchar_t const*)fileName, &buf) != 0)
  962. return -1; // error, could use errno to find out more
  963. return buf.st_size;
  964. }
  965. int FindNoCaseAndInsert(CString& mainStr, CString& findStr, CString preInsert, CString postInsert, int linesPerRow)
  966. {
  967. int replaceCount = 0;
  968. //Prevent infinite loop when user tries to replace nothing.
  969. if (findStr != "")
  970. {
  971. int oldLen = findStr.GetLength();
  972. int foundPos = 0;
  973. int startFindPos = 0;
  974. int newPos = 0;
  975. int insertedLength = 0;
  976. int firstFindPos = 0;
  977. //use icu::UnicodeString because it handles upper/lowercase characters for all languages, CSTring only hanldes ascii characters
  978. icu::UnicodeString mainLow(mainStr);
  979. mainLow.foldCase(U_FOLD_CASE_DEFAULT);
  980. icu::UnicodeString findLow(findStr);
  981. findLow.foldCase(U_FOLD_CASE_DEFAULT);
  982. int preLength = preInsert.GetLength();
  983. int postLength = postInsert.GetLength();
  984. int x = mainLow.indexOf(findLow, 0);
  985. while(TRUE)
  986. {
  987. foundPos = mainLow.indexOf(findLow, startFindPos);
  988. if (foundPos < 0)
  989. break;
  990. if (replaceCount == 0)
  991. {
  992. firstFindPos = foundPos + preLength;
  993. }
  994. newPos = foundPos + insertedLength;
  995. mainStr.Insert(newPos, preInsert);
  996. mainStr.Insert(newPos + preLength + oldLen, postInsert);
  997. startFindPos = foundPos + oldLen;
  998. insertedLength += preLength + postLength;
  999. replaceCount++;
  1000. //safety check, make sure we don't look forever
  1001. if (replaceCount > 100)
  1002. break;
  1003. }
  1004. startFindPos = 0;
  1005. int line = 0;
  1006. int prevLinePos = 0;
  1007. int prevPrevLinePos = 0;
  1008. while (TRUE)
  1009. {
  1010. foundPos = mainStr.Find(_T("\n"), startFindPos);
  1011. if (foundPos < 0)
  1012. break;
  1013. if (firstFindPos < foundPos)
  1014. {
  1015. if (line > linesPerRow - 1)
  1016. {
  1017. int lineStart = prevLinePos;
  1018. if (linesPerRow > 1)
  1019. {
  1020. lineStart = prevPrevLinePos;
  1021. }
  1022. mainStr = _T("... ") + mainStr.Mid(lineStart + 1);
  1023. }
  1024. break;
  1025. }
  1026. startFindPos = foundPos + 1;
  1027. prevPrevLinePos = prevLinePos;
  1028. prevLinePos = foundPos;
  1029. line++;
  1030. //safety check, make sure we don't look forever
  1031. if (line > 1000)
  1032. break;
  1033. }
  1034. if(replaceCount > 0)
  1035. {
  1036. //use unprintable characters so it doesn't find copied html to convert
  1037. mainStr.Replace(_T("\r\n"), _T("\x01\x05\x02"));
  1038. int l = mainStr.Replace(_T("\r"), _T("\x01\x05\x02"));
  1039. int m = mainStr.Replace(_T("\n"), _T("\x01\x05\x02"));
  1040. }
  1041. }
  1042. return replaceCount;
  1043. }
  1044. void OnInitMenuPopupEx(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu, CWnd *pWnd)
  1045. {
  1046. ASSERT(pPopupMenu != NULL);
  1047. // Check the enabled state of various menu items.
  1048. CCmdUI state;
  1049. state.m_pMenu = pPopupMenu;
  1050. ASSERT(state.m_pOther == NULL);
  1051. ASSERT(state.m_pParentMenu == NULL);
  1052. // Determine if menu is popup in top-level menu and set m_pOther to
  1053. // it if so (m_pParentMenu == NULL indicates that it is secondary popup).
  1054. HMENU hParentMenu;
  1055. if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)
  1056. {
  1057. state.m_pParentMenu = pPopupMenu; // Parent == child for tracking popup.
  1058. }
  1059. else if ((hParentMenu = ::GetMenu(pWnd->m_hWnd)) != NULL)
  1060. {
  1061. CWnd* pParent = pWnd;
  1062. // Child windows don't have menus--need to go to the top!
  1063. if (pParent != NULL &&
  1064. (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
  1065. {
  1066. int nIndexMax = ::GetMenuItemCount(hParentMenu);
  1067. for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
  1068. {
  1069. if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu)
  1070. {
  1071. // When popup is found, m_pParentMenu is containing menu.
  1072. state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
  1073. break;
  1074. }
  1075. }
  1076. }
  1077. }
  1078. state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
  1079. for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  1080. state.m_nIndex++)
  1081. {
  1082. state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex);
  1083. if (state.m_nID == 0)
  1084. continue; // Menu separator or invalid cmd - ignore it.
  1085. ASSERT(state.m_pOther == NULL);
  1086. ASSERT(state.m_pMenu != NULL);
  1087. if (state.m_nID == (UINT)-1)
  1088. {
  1089. // Possibly a popup menu, route to first item of that popup.
  1090. state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
  1091. if (state.m_pSubMenu == NULL ||
  1092. (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
  1093. state.m_nID == (UINT)-1)
  1094. {
  1095. continue; // First item of popup can't be routed to.
  1096. }
  1097. state.DoUpdate(pWnd, TRUE); // Popups are never auto disabled.
  1098. }
  1099. else
  1100. {
  1101. // Normal menu item.
  1102. // Auto enable/disable if frame window has m_bAutoMenuEnable
  1103. // set and command is _not_ a system command.
  1104. state.m_pSubMenu = NULL;
  1105. state.DoUpdate(pWnd, FALSE);
  1106. }
  1107. // Adjust for menu deletions and additions.
  1108. UINT nCount = pPopupMenu->GetMenuItemCount();
  1109. if (nCount < state.m_nIndexMax)
  1110. {
  1111. state.m_nIndex -= (state.m_nIndexMax - nCount);
  1112. while (state.m_nIndex < nCount &&
  1113. pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
  1114. {
  1115. state.m_nIndex++;
  1116. }
  1117. }
  1118. state.m_nIndexMax = nCount;
  1119. }
  1120. }
  1121. CString InternetEncode(CString text)
  1122. {
  1123. CString ret = _T("");
  1124. LPTSTR lpOutputBuffer = new TCHAR[1];
  1125. DWORD dwSize = 1;
  1126. BOOL fRes = ::InternetCanonicalizeUrl(text, lpOutputBuffer, &dwSize, ICU_BROWSER_MODE);
  1127. DWORD dwError = ::GetLastError();
  1128. if (!fRes && dwError == ERROR_INSUFFICIENT_BUFFER)
  1129. {
  1130. delete lpOutputBuffer;
  1131. lpOutputBuffer = new TCHAR[dwSize];
  1132. fRes = ::InternetCanonicalizeUrl(text, lpOutputBuffer, &dwSize, ICU_BROWSER_MODE);
  1133. if (fRes)
  1134. {
  1135. ret = lpOutputBuffer;
  1136. //lpOutputBuffer has decoded url
  1137. }
  1138. else
  1139. {
  1140. //failed to decode
  1141. }
  1142. if (lpOutputBuffer != NULL)
  1143. {
  1144. delete [] lpOutputBuffer;
  1145. lpOutputBuffer = NULL;
  1146. }
  1147. }
  1148. else
  1149. {
  1150. //some other error OR the input string url is just 1 char and was successfully decoded
  1151. }
  1152. return ret;
  1153. }
  1154. void DeleteParamFromRTF(CStringA &test, CStringA find, bool searchForTrailingDigits)
  1155. {
  1156. int start = 0;
  1157. while (start >= 0)
  1158. {
  1159. start = test.Find(find, start);
  1160. if (start >= 0)
  1161. {
  1162. if (start > 0)
  1163. {
  1164. //leave it if the preceding character is \\, i was seeing the double slash if the actual text contained slash
  1165. if (test[start - 1] == '\\')
  1166. {
  1167. start++;
  1168. continue;
  1169. }
  1170. }
  1171. int end = -1;
  1172. int innerStart = start + find.GetLength();
  1173. if (searchForTrailingDigits)
  1174. {
  1175. for (int i = innerStart; i < test.GetLength(); i++)
  1176. {
  1177. if (isdigit(test[i]) == false)
  1178. {
  1179. end = i;
  1180. break;
  1181. }
  1182. }
  1183. }
  1184. else
  1185. {
  1186. end = innerStart;
  1187. }
  1188. if (end > 0)
  1189. {
  1190. if (searchForTrailingDigits == false ||
  1191. end != innerStart)
  1192. {
  1193. test.Delete(start, (end - start));
  1194. }
  1195. else
  1196. {
  1197. start++;
  1198. }
  1199. }
  1200. else
  1201. {
  1202. break;
  1203. }
  1204. }
  1205. }
  1206. }
  1207. bool RemoveRTFSection(CStringA &str, CStringA section)
  1208. {
  1209. bool removedSection = false;
  1210. int start2 = str.Find(section, 0);
  1211. int end2 = 0;
  1212. if (start2 >= 0)
  1213. {
  1214. int in = 0;
  1215. for (int pos = start2+1; pos < str.GetLength(); pos++)
  1216. {
  1217. if (str[pos] == '{')
  1218. {
  1219. in++;
  1220. }
  1221. if (str[pos] == '}')
  1222. {
  1223. if (in > 0)
  1224. {
  1225. in--;
  1226. }
  1227. else
  1228. {
  1229. end2 = pos;
  1230. break;
  1231. }
  1232. }
  1233. }
  1234. if (end2 > start2)
  1235. {
  1236. str.Delete(start2, (end2 - start2) + 1);
  1237. removedSection = true;
  1238. }
  1239. }
  1240. return removedSection;
  1241. }
  1242. CString NewGuidString()
  1243. {
  1244. CString guidString;
  1245. GUID guid;
  1246. CoCreateGuid(&guid);
  1247. guidString.Format(_T("%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX"),
  1248. guid.Data1, guid.Data2, guid.Data3,
  1249. guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
  1250. guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
  1251. return guidString;
  1252. }
  1253. CString FolderPath(int folderId)
  1254. {
  1255. CString folder = _T("");
  1256. if (folderId > 0)
  1257. {
  1258. try
  1259. {
  1260. CStringArray arr;
  1261. for (int i = 0; i < 100; i++)
  1262. {
  1263. CppSQLite3Query parent = theApp.m_db.execQueryEx(_T("SELECT lID, mText, lParentID FROM Main WHERE lID = %d"), folderId);
  1264. if (parent.eof() == false)
  1265. {
  1266. arr.Add(parent.getStringField(_T("mText")));
  1267. folderId = parent.getIntField(_T("lParentID"));
  1268. }
  1269. else
  1270. {
  1271. break;
  1272. }
  1273. }
  1274. folder = _T("Group Path: \\");
  1275. for (int folderPos = arr.GetCount() - 1; folderPos >= 0; folderPos--)
  1276. {
  1277. folder += _T("\\");
  1278. folder += arr[folderPos];
  1279. }
  1280. }
  1281. CATCH_SQLITE_EXCEPTION
  1282. }
  1283. return folder;
  1284. }