Misc.cpp 32 KB

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