1
0

CMakeSetupDialog.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459
  1. // pcbuilderdialogDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "shellapi.h"
  5. // a fun undef for DOT NET
  6. #undef DEBUG
  7. #include "CMakeSetup.h"
  8. #include "MakeHelp.h"
  9. #include "PathDialog.h"
  10. #include "CMakeSetupDialog.h"
  11. #include "CMakeCommandLineInfo.h"
  12. #include "../cmListFileCache.h"
  13. #include "../cmCacheManager.h"
  14. #include "../cmake.h"
  15. #include "../cmGlobalGenerator.h"
  16. #include "../cmDynamicLoader.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CAboutDlg dialog used for App About
  24. class CAboutDlg : public CDialog
  25. {
  26. public:
  27. CAboutDlg();
  28. // Dialog Data
  29. //{{AFX_DATA(CAboutDlg)
  30. enum { IDD = IDD_ABOUTBOX };
  31. //}}AFX_DATA
  32. // ClassWizard generated virtual function overrides
  33. //{{AFX_VIRTUAL(CAboutDlg)
  34. protected:
  35. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  36. //}}AFX_VIRTUAL
  37. // Implementation
  38. protected:
  39. //{{AFX_MSG(CAboutDlg)
  40. //}}AFX_MSG
  41. DECLARE_MESSAGE_MAP()
  42. };
  43. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  44. {
  45. //{{AFX_DATA_INIT(CAboutDlg)
  46. //}}AFX_DATA_INIT
  47. }
  48. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  49. {
  50. CDialog::DoDataExchange(pDX);
  51. //{{AFX_DATA_MAP(CAboutDlg)
  52. //}}AFX_DATA_MAP
  53. }
  54. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  55. //{{AFX_MSG_MAP(CAboutDlg)
  56. // No message handlers
  57. //}}AFX_MSG_MAP
  58. END_MESSAGE_MAP();
  59. void MFCMessageCallback(const char* m, const char* title, bool& nomore, void*)
  60. {
  61. std::string message = m;
  62. message += "\n\n(Press Cancel to suppress any further messages.)";
  63. if(::MessageBox(0, message.c_str(), title,
  64. MB_OKCANCEL|MB_TASKMODAL) == IDCANCEL)
  65. {
  66. nomore = true;
  67. }
  68. }
  69. /////////////////////////////////////////////////////////////////////////////
  70. // CMakeSetupDialog dialog
  71. void updateProgress(const char *msg, float prog, void *cd)
  72. {
  73. char tmp[1024];
  74. if (prog >= 0)
  75. {
  76. sprintf(tmp,"%s %i%%",msg,(int)(100*prog));
  77. }
  78. else
  79. {
  80. sprintf(tmp,"%s",msg);
  81. }
  82. CMakeSetupDialog *self = (CMakeSetupDialog *)cd;
  83. self->SetDlgItemText(IDC_PROGRESS, tmp);
  84. CWnd* cancel = self->GetDlgItem(IDCANCEL);
  85. //
  86. // Retrieve and dispatch any waiting messages.
  87. //
  88. MSG wmsg;
  89. while (::PeekMessage (&wmsg, NULL, 0, 0, PM_REMOVE))
  90. {
  91. switch(wmsg.message)
  92. {
  93. case WM_LBUTTONDOWN:
  94. case WM_LBUTTONUP:
  95. case WM_LBUTTONDBLCLK:
  96. {
  97. if(wmsg.hwnd == cancel->m_hWnd)
  98. {
  99. ::DispatchMessage(&wmsg);
  100. }
  101. }
  102. break;
  103. case WM_COMMAND:
  104. case WM_SETCURSOR:
  105. case WM_PAINT:
  106. ::DispatchMessage(&wmsg);
  107. break;
  108. }
  109. }
  110. }
  111. // Convert to Win32 path (slashes). This calls the system tools one and then
  112. // removes the spaces. It is not in system tools because we don't want any
  113. // generators accidentally use it
  114. std::string ConvertToWindowsPath(const char* path)
  115. {
  116. // Convert to output path.
  117. // Remove the "" around it (if any) since it's an output path for
  118. // the shell. If another shell-oriented feature is not designed
  119. // for a GUI use, then we are in trouble.
  120. std::string s = cmSystemTools::ConvertToOutputPath(path);
  121. if (s.size())
  122. {
  123. std::string::iterator i = s.begin();
  124. if (*i == '\"')
  125. {
  126. s.erase(i, i + 1);
  127. }
  128. i = s.begin() + s.length() - 1;
  129. if (*i == '\"')
  130. {
  131. s.erase(i, i + 1);
  132. }
  133. }
  134. return s;
  135. }
  136. CMakeSetupDialog::CMakeSetupDialog(const CMakeCommandLineInfo& cmdInfo,
  137. CWnd* pParent /*=NULL*/)
  138. : CDialog(CMakeSetupDialog::IDD, pParent)
  139. {
  140. m_Cursor = LoadCursor(NULL, IDC_ARROW);
  141. m_RunningConfigure = false;
  142. cmSystemTools::SetRunCommandHideConsole(true);
  143. cmSystemTools::SetErrorCallback(MFCMessageCallback);
  144. m_RegistryKey = "Software\\Kitware\\CMakeSetup\\Settings\\StartPath";
  145. m_CacheEntriesList.m_CMakeSetupDialog = this;
  146. m_CMakeInstance = new cmake;
  147. m_CMakeInstance->SetProgressCallback(updateProgress, (void *)this);
  148. //{{AFX_DATA_INIT(CMakeSetupDialog)
  149. //}}AFX_DATA_INIT
  150. // Get the parameters from the command line info
  151. // If an unknown parameter is found, try to interpret it too, since it
  152. // is likely to be a file dropped on the shortcut :)
  153. if (cmdInfo.m_LastUnknownParameter.IsEmpty())
  154. {
  155. this->m_WhereSource = cmdInfo.m_WhereSource;
  156. this->m_WhereBuild = cmdInfo.m_WhereBuild;
  157. this->m_GeneratorChoiceString = cmdInfo.m_GeneratorChoiceString;
  158. this->m_AdvancedValues = cmdInfo.m_AdvancedValues;
  159. }
  160. else
  161. {
  162. this->m_WhereSource = _T("");
  163. this->m_WhereBuild = _T("");
  164. this->m_AdvancedValues = FALSE;
  165. this->m_GeneratorChoiceString = cmdInfo.m_GeneratorChoiceString;
  166. this->ChangeDirectoriesFromFile((LPCTSTR)cmdInfo.m_LastUnknownParameter);
  167. }
  168. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  169. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  170. m_BuildPathChanged = false;
  171. // Find the path to the cmake.exe executable
  172. char fname[1024];
  173. ::GetModuleFileName(NULL,fname,1023);
  174. // extract just the path part
  175. m_PathToExecutable = cmSystemTools::GetProgramPath(fname).c_str();
  176. // add the cmake.exe to the path
  177. m_PathToExecutable += "/cmake.exe";
  178. m_oldCX = -1;
  179. m_deltaXRemainder = 0;
  180. }
  181. CMakeSetupDialog::~CMakeSetupDialog()
  182. {
  183. delete m_CMakeInstance;
  184. // clean up globals
  185. cmListFileCache::GetInstance()->ClearCache();
  186. cmDynamicLoader::FlushCache();
  187. }
  188. void CMakeSetupDialog::DoDataExchange(CDataExchange* pDX)
  189. {
  190. CDialog::DoDataExchange(pDX);
  191. //{{AFX_DATA_MAP(CMakeSetupDialog)
  192. DDX_Control(pDX, IDC_AdvancedValues, m_AdvancedValuesControl);
  193. DDX_Control(pDX, IDC_BuildForLabel, m_BuildForLabel);
  194. DDX_Control(pDX, IDC_BROWSE_SOURCE, m_BrowseSource);
  195. DDX_Control(pDX, IDC_BROWSE_BUILD, m_BrowseBuild);
  196. DDX_Control(pDX, IDC_DELETE_BUTTON, m_DeleteButton);
  197. DDX_Control(pDX, IDC_HELP_BUTTON, m_HelpButton);
  198. DDX_Control(pDX, IDC_Generator, m_GeneratorChoice);
  199. DDX_Control(pDX, IDC_OK, m_OKButton);
  200. DDX_Control(pDX, IDCANCEL, m_CancelButton);
  201. DDX_CBStringExact(pDX, IDC_WhereSource, m_WhereSource);
  202. DDX_CBStringExact(pDX, IDC_WhereBuild, m_WhereBuild);
  203. DDX_Control(pDX, IDC_FRAME, m_ListFrame);
  204. DDX_Control(pDX, IDC_WhereSource, m_WhereSourceControl);
  205. DDX_Control(pDX, IDC_WhereBuild, m_WhereBuildControl);
  206. DDX_Control(pDX, IDC_LIST2, m_CacheEntriesList);
  207. DDX_Control(pDX, IDC_MouseHelpCaption, m_MouseHelp);
  208. DDX_Control(pDX, IDC_PROGRESS, m_StatusDisplay);
  209. DDX_Control(pDX, IDC_BuildProjects, m_Configure);
  210. DDX_CBStringExact(pDX, IDC_Generator, m_GeneratorChoiceString);
  211. DDX_Check(pDX, IDC_AdvancedValues, m_AdvancedValues);
  212. //}}AFX_DATA_MAP
  213. }
  214. BEGIN_MESSAGE_MAP(CMakeSetupDialog, CDialog)
  215. //{{AFX_MSG_MAP(CMakeSetupDialog)
  216. ON_WM_SYSCOMMAND()
  217. ON_WM_PAINT()
  218. ON_WM_QUERYDRAGICON()
  219. ON_BN_CLICKED(IDC_BUTTON2, OnBrowseWhereSource)
  220. ON_BN_CLICKED(IDC_BuildProjects, OnConfigure)
  221. ON_BN_CLICKED(IDC_BUTTON3, OnBrowseWhereBuild)
  222. ON_CBN_EDITCHANGE(IDC_WhereBuild, OnChangeWhereBuild)
  223. ON_CBN_SELCHANGE(IDC_WhereBuild, OnSelendokWhereBuild)
  224. ON_CBN_EDITCHANGE(IDC_WhereSource, OnChangeWhereSource)
  225. ON_CBN_SELENDOK(IDC_WhereSource, OnSelendokWhereSource)
  226. ON_WM_SIZE()
  227. ON_WM_GETMINMAXINFO()
  228. ON_BN_CLICKED(IDC_OK, OnOk)
  229. ON_CBN_EDITCHANGE(IDC_Generator, OnEditchangeGenerator)
  230. ON_BN_CLICKED(IDC_DELETE_BUTTON, OnDeleteButton)
  231. ON_BN_CLICKED(IDC_HELP_BUTTON, OnHelpButton)
  232. ON_BN_CLICKED(IDC_AdvancedValues, OnAdvancedValues)
  233. ON_BN_DOUBLECLICKED(IDC_AdvancedValues, OnDoubleclickedAdvancedValues)
  234. ON_WM_DROPFILES()
  235. ON_BN_CLICKED(IDCANCEL, OnCancel)
  236. ON_WM_SETCURSOR()
  237. //}}AFX_MSG_MAP
  238. END_MESSAGE_MAP()
  239. /////////////////////////////////////////////////////////////////////////////
  240. // CMakeSetupDialog message handlers
  241. BOOL CMakeSetupDialog::OnInitDialog()
  242. {
  243. CDialog::OnInitDialog();
  244. this->DragAcceptFiles(true);
  245. // Add "Create shortcut" menu item to system menu.
  246. // IDM_CREATESHORTCUT must be in the system command range.
  247. ASSERT((IDM_CREATESHORTCUT & 0xFFF0) == IDM_CREATESHORTCUT);
  248. ASSERT(IDM_CREATESHORTCUT < 0xF000);
  249. // Add "About..." menu item to system menu.
  250. // IDM_ABOUTBOX must be in the system command range.
  251. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  252. ASSERT(IDM_ABOUTBOX < 0xF000);
  253. CMenu* pSysMenu = GetSystemMenu(FALSE);
  254. if (pSysMenu != NULL)
  255. {
  256. CString strCreateShortcutMenu;
  257. strCreateShortcutMenu.LoadString(IDS_CREATESHORTCUT);
  258. if (!strCreateShortcutMenu.IsEmpty())
  259. {
  260. pSysMenu->AppendMenu(MF_SEPARATOR);
  261. pSysMenu->AppendMenu(MF_STRING,
  262. IDM_CREATESHORTCUT,
  263. strCreateShortcutMenu);
  264. }
  265. CString strAboutMenu;
  266. strAboutMenu.LoadString(IDS_ABOUTBOX);
  267. if (!strAboutMenu.IsEmpty())
  268. {
  269. pSysMenu->AppendMenu(MF_SEPARATOR);
  270. pSysMenu->AppendMenu(MF_STRING,
  271. IDM_ABOUTBOX,
  272. strAboutMenu);
  273. }
  274. }
  275. // Set the icon for this dialog. The framework does this automatically
  276. // when the application's main window is not a dialog
  277. SetIcon(m_hIcon, TRUE); // Set big icon
  278. SetIcon(m_hIcon, FALSE); // Set small icon
  279. // Load source and build dirs from registry
  280. this->LoadFromRegistry();
  281. std::vector<std::string> names;
  282. this->m_CMakeInstance->GetRegisteredGenerators(names);
  283. for(std::vector<std::string>::iterator i = names.begin();
  284. i != names.end(); ++i)
  285. {
  286. m_GeneratorChoice.AddString(i->c_str());
  287. }
  288. if (m_GeneratorChoiceString == _T(""))
  289. {
  290. // check for vs7 in registry then decide what default to use
  291. std::string mp;
  292. mp = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]";
  293. cmSystemTools::ExpandRegistryValues(mp);
  294. if (mp != "/registry")
  295. {
  296. m_GeneratorChoiceString = "Visual Studio 7 .NET 2003";
  297. }
  298. else
  299. {
  300. mp = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.0;InstallDir]";
  301. cmSystemTools::ExpandRegistryValues(mp);
  302. if (mp != "/registry")
  303. {
  304. m_GeneratorChoiceString = "Visual Studio 7";
  305. }
  306. else
  307. {
  308. m_GeneratorChoiceString = "Visual Studio 6";
  309. }
  310. }
  311. }
  312. // try to load the cmake cache from disk
  313. this->LoadCacheFromDiskToGUI();
  314. m_WhereBuildControl.LimitText(2048);
  315. m_WhereSourceControl.LimitText(2048);
  316. m_GeneratorChoice.LimitText(2048);
  317. // Set the version number
  318. char tmp[1024];
  319. sprintf(tmp,"CMake %d.%d - %s", cmake::GetMajorVersion(),
  320. cmake::GetMinorVersion(), cmake::GetReleaseVersion());
  321. SetDlgItemText(IDC_PROGRESS, "");
  322. this->SetWindowText(tmp);
  323. this->UpdateData(FALSE);
  324. return TRUE; // return TRUE unless you set the focus to a control
  325. }
  326. // About dialog invoke
  327. void CMakeSetupDialog::OnSysCommand(UINT nID, LPARAM lParam)
  328. {
  329. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  330. {
  331. CAboutDlg dlgAbout;
  332. dlgAbout.DoModal();
  333. }
  334. else if ((nID & 0xFFF0) == IDM_CREATESHORTCUT)
  335. {
  336. CreateShortcut();
  337. }
  338. else
  339. {
  340. CDialog::OnSysCommand(nID, lParam);
  341. }
  342. }
  343. // If you add a minimize button to your dialog, you will need the code below
  344. // to draw the icon. For MFC applications using the document/view model,
  345. // this is automatically done for you by the framework.
  346. void CMakeSetupDialog::OnPaint()
  347. {
  348. if (IsIconic())
  349. {
  350. CPaintDC dc(this); // device context for painting
  351. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  352. // Center icon in client rectangle
  353. int cxIcon = GetSystemMetrics(SM_CXICON);
  354. int cyIcon = GetSystemMetrics(SM_CYICON);
  355. CRect rect;
  356. GetClientRect(&rect);
  357. int x = (rect.Width() - cxIcon + 1) / 2;
  358. int y = (rect.Height() - cyIcon + 1) / 2;
  359. // Draw the icon
  360. dc.DrawIcon(x, y, m_hIcon);
  361. }
  362. else
  363. {
  364. CDialog::OnPaint();
  365. }
  366. }
  367. // The system calls this to obtain the cursor to display while the user drags
  368. // the minimized window.
  369. HCURSOR CMakeSetupDialog::OnQueryDragIcon()
  370. {
  371. return (HCURSOR) m_hIcon;
  372. }
  373. // Browse button
  374. bool CMakeSetupDialog::Browse(CString &result, const char *title)
  375. {
  376. CPathDialog dlg("Select Path", title, result);
  377. if(dlg.DoModal()==IDOK)
  378. {
  379. result = dlg.GetPathName();
  380. return true;
  381. }
  382. else
  383. {
  384. return false;
  385. }
  386. }
  387. void CMakeSetupDialog::SaveToRegistry()
  388. {
  389. HKEY hKey;
  390. DWORD dwDummy;
  391. if(RegCreateKeyEx(HKEY_CURRENT_USER,
  392. m_RegistryKey,
  393. 0, "", REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
  394. NULL, &hKey, &dwDummy) != ERROR_SUCCESS)
  395. {
  396. return;
  397. }
  398. else
  399. {
  400. // save some values
  401. CString regvalue;
  402. this->ReadRegistryValue(hKey, &(regvalue),"WhereSource1","C:\\");
  403. int shiftEnd = 9;
  404. if(m_WhereSource != regvalue)
  405. {
  406. char keyName[1024];
  407. char keyName2[1024];
  408. int i;
  409. for (i = 2; i < 10; ++i)
  410. {
  411. regvalue = "";
  412. sprintf(keyName,"WhereSource%i",i);
  413. this->ReadRegistryValue(hKey, &(regvalue),keyName,"");
  414. // check for short circuit, if the new value is already in
  415. // the list then we stop
  416. if (m_WhereSource == regvalue)
  417. {
  418. shiftEnd = i - 1;
  419. }
  420. }
  421. for (i = shiftEnd; i; --i)
  422. {
  423. regvalue = "";
  424. sprintf(keyName,"WhereSource%i",i);
  425. sprintf(keyName2,"WhereSource%i",i+1);
  426. this->ReadRegistryValue(hKey, &(regvalue),keyName,"");
  427. if (strlen(regvalue))
  428. {
  429. RegSetValueEx(hKey, _T(keyName2), 0, REG_SZ,
  430. (CONST BYTE *)(const char *)regvalue,
  431. regvalue.GetLength());
  432. }
  433. }
  434. RegSetValueEx(hKey, _T("WhereSource1"), 0, REG_SZ,
  435. (CONST BYTE *)(const char *)m_WhereSource,
  436. m_WhereSource.GetLength());
  437. }
  438. this->ReadRegistryValue(hKey, &(regvalue),"WhereBuild1","C:\\");
  439. if(m_WhereBuild != regvalue)
  440. {
  441. int i;
  442. char keyName[1024];
  443. char keyName2[1024];
  444. for (i = 2; i < 10; ++i)
  445. {
  446. regvalue = "";
  447. sprintf(keyName,"WhereBuild%i",i);
  448. this->ReadRegistryValue(hKey, &(regvalue),keyName,"");
  449. // check for short circuit, if the new value is already in
  450. // the list then we stop
  451. if (m_WhereBuild == regvalue)
  452. {
  453. shiftEnd = i - 1;
  454. }
  455. }
  456. for (i = shiftEnd; i; --i)
  457. {
  458. regvalue = "";
  459. sprintf(keyName,"WhereBuild%i",i);
  460. sprintf(keyName2,"WhereBuild%i",i+1);
  461. this->ReadRegistryValue(hKey, &(regvalue),keyName,"");
  462. if (strlen(regvalue))
  463. {
  464. RegSetValueEx(hKey, _T(keyName2), 0, REG_SZ,
  465. (CONST BYTE *)(const char *)regvalue,
  466. regvalue.GetLength());
  467. }
  468. }
  469. RegSetValueEx(hKey, _T("WhereBuild1"), 0, REG_SZ,
  470. (CONST BYTE *)(const char *)m_WhereBuild,
  471. m_WhereBuild.GetLength());
  472. }
  473. }
  474. RegCloseKey(hKey);
  475. }
  476. void CMakeSetupDialog::ReadRegistryValue(HKEY hKey,
  477. CString *val,
  478. const char *key,
  479. const char *adefault)
  480. {
  481. DWORD dwType, dwSize;
  482. char *pb;
  483. dwType = REG_SZ;
  484. pb = val->GetBuffer(MAX_PATH);
  485. dwSize = MAX_PATH;
  486. if(RegQueryValueEx(hKey,_T(key), NULL, &dwType,
  487. (BYTE *)pb, &dwSize) != ERROR_SUCCESS)
  488. {
  489. val->ReleaseBuffer();
  490. *val = _T(adefault);
  491. }
  492. else
  493. {
  494. val->ReleaseBuffer();
  495. }
  496. }
  497. void CMakeSetupDialog::LoadFromRegistry()
  498. {
  499. HKEY hKey;
  500. if(RegOpenKeyEx(HKEY_CURRENT_USER,
  501. m_RegistryKey,
  502. 0, KEY_READ, &hKey) != ERROR_SUCCESS)
  503. {
  504. return;
  505. }
  506. else
  507. {
  508. // load some values
  509. if (m_WhereSource.IsEmpty())
  510. {
  511. this->ReadRegistryValue(hKey, &(m_WhereSource),"WhereSource1","C:\\");
  512. }
  513. if (m_WhereBuild.IsEmpty())
  514. {
  515. this->ReadRegistryValue(hKey, &(m_WhereBuild),"WhereBuild1","C:\\");
  516. }
  517. m_WhereSourceControl.AddString(m_WhereSource);
  518. m_WhereBuildControl.AddString(m_WhereBuild);
  519. char keyname[1024];
  520. CString regvalue;
  521. int i;
  522. for (i = 2; i <= 10; ++i)
  523. {
  524. sprintf(keyname,"WhereSource%i",i);
  525. regvalue = "";
  526. this->ReadRegistryValue(hKey, &(regvalue),keyname,"C:\\");
  527. if (strcmp("C:\\",regvalue))
  528. {
  529. m_WhereSourceControl.AddString(regvalue);
  530. }
  531. sprintf(keyname,"WhereBuild%i",i);
  532. regvalue = "";
  533. this->ReadRegistryValue(hKey, &(regvalue),keyname,"C:\\");
  534. if (strcmp("C:\\",regvalue))
  535. {
  536. m_WhereBuildControl.AddString(regvalue);
  537. }
  538. }
  539. }
  540. RegCloseKey(hKey);
  541. }
  542. // Callback for browse source button
  543. void CMakeSetupDialog::OnBrowseWhereSource()
  544. {
  545. this->UpdateData();
  546. Browse(m_WhereSource, "Enter Path to Source");
  547. this->UpdateData(false);
  548. this->OnChangeWhereSource();
  549. }
  550. // Callback for browser build button
  551. void CMakeSetupDialog::OnBrowseWhereBuild()
  552. {
  553. this->UpdateData();
  554. Browse(m_WhereBuild, "Enter Path to Build");
  555. this->UpdateData(false);
  556. this->OnChangeWhereBuild();
  557. }
  558. void CMakeSetupDialog::RunCMake(bool generateProjectFiles)
  559. {
  560. if(!cmSystemTools::FileExists(m_WhereBuild))
  561. {
  562. std::string message =
  563. "Build directory does not exist, should I create it?\n\n"
  564. "Directory: ";
  565. message += (const char*)m_WhereBuild;
  566. if(MessageBox(message.c_str(), "Create Directory", MB_OKCANCEL) == IDOK)
  567. {
  568. cmSystemTools::MakeDirectory(m_WhereBuild);
  569. }
  570. else
  571. {
  572. MessageBox("Build Project aborted, nothing done.");
  573. return;
  574. }
  575. }
  576. // set the wait cursor
  577. m_Cursor = LoadCursor(NULL, IDC_WAIT);
  578. ::SetCursor(m_Cursor);
  579. m_RunningConfigure = true;
  580. // get all the info from the dialog
  581. this->UpdateData();
  582. // always save the current gui values to disk
  583. this->SaveCacheFromGUI();
  584. // Make sure we are working from the cache on disk
  585. this->LoadCacheFromDiskToGUI();
  586. m_OKButton.EnableWindow(false);
  587. // setup the cmake instance
  588. if (generateProjectFiles)
  589. {
  590. if(m_CMakeInstance->Generate() != 0)
  591. {
  592. cmSystemTools::Error(
  593. "Error in generation process, project files may be invalid");
  594. }
  595. }
  596. else
  597. {
  598. m_CMakeInstance->SetHomeDirectory(m_WhereSource);
  599. m_CMakeInstance->SetStartDirectory(m_WhereSource);
  600. m_CMakeInstance->SetHomeOutputDirectory(m_WhereBuild);
  601. m_CMakeInstance->SetStartOutputDirectory(m_WhereBuild);
  602. m_CMakeInstance->SetGlobalGenerator(
  603. m_CMakeInstance->CreateGlobalGenerator(m_GeneratorChoiceString));
  604. m_CMakeInstance->SetCMakeCommand(m_PathToExecutable);
  605. m_CMakeInstance->LoadCache();
  606. if(m_CMakeInstance->Configure() != 0)
  607. {
  608. cmSystemTools::Error(
  609. "Error in configuration process, project files may be invalid");
  610. }
  611. // update the GUI with any new values in the caused by the
  612. // generation process
  613. this->LoadCacheFromDiskToGUI();
  614. }
  615. // save source and build paths to registry
  616. this->SaveToRegistry();
  617. // path is up-to-date now
  618. m_BuildPathChanged = false;
  619. // put the cursor back
  620. m_Cursor = LoadCursor(NULL, IDC_ARROW);
  621. ::SetCursor(m_Cursor);
  622. m_RunningConfigure = false;
  623. cmSystemTools::ResetErrorOccuredFlag();
  624. }
  625. // Callback for build projects button
  626. void CMakeSetupDialog::OnConfigure()
  627. {
  628. // enable error messages each time configure is pressed
  629. cmSystemTools::EnableMessages();
  630. this->RunCMake(false);
  631. }
  632. // callback for combo box menu where build selection
  633. void CMakeSetupDialog::OnSelendokWhereBuild()
  634. {
  635. m_WhereBuildControl.GetLBText(m_WhereBuildControl.GetCurSel(),
  636. m_WhereBuild);
  637. m_WhereBuildControl.SetWindowText( m_WhereBuild);
  638. this->UpdateData(FALSE);
  639. this->OnChangeWhereBuild();
  640. }
  641. // callback for combo box menu where source selection
  642. void CMakeSetupDialog::OnSelendokWhereSource()
  643. {
  644. m_WhereSourceControl.GetLBText(m_WhereSourceControl.GetCurSel(),
  645. m_WhereSource);
  646. this->UpdateData(FALSE);
  647. this->OnChangeWhereSource();
  648. }
  649. // callback for chaing source directory
  650. void CMakeSetupDialog::OnChangeWhereSource()
  651. {
  652. }
  653. // callback for changing the build directory
  654. void CMakeSetupDialog::OnChangeWhereBuild()
  655. {
  656. this->UpdateData();
  657. // The build dir has changed, check if there is a cache, and
  658. // grab the source dir from it
  659. std::string path = this->m_WhereBuild;
  660. cmSystemTools::ConvertToUnixSlashes(path);
  661. // adjust the cmake instance
  662. m_CMakeInstance->SetHomeOutputDirectory(m_WhereBuild);
  663. m_CMakeInstance->SetStartOutputDirectory(m_WhereBuild);
  664. std::string cache_file = path;
  665. cache_file += "/CMakeCache.txt";
  666. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  667. cmCacheManager::CacheIterator it = cachem->NewIterator();
  668. if (cmSystemTools::FileExists(cache_file.c_str()) &&
  669. cachem->LoadCache(path.c_str()) &&
  670. it.Find("CMAKE_HOME_DIRECTORY"))
  671. {
  672. path = ConvertToWindowsPath(it.GetValue());
  673. this->m_WhereSource = path.c_str();
  674. this->m_WhereSourceControl.SetWindowText(this->m_WhereSource);
  675. this->OnChangeWhereSource();
  676. }
  677. m_CacheEntriesList.RemoveAll();
  678. m_CacheEntriesList.ShowWindow(SW_SHOW);
  679. this->LoadCacheFromDiskToGUI();
  680. m_BuildPathChanged = true;
  681. }
  682. // copy from the cache manager to the cache edit list box
  683. void CMakeSetupDialog::FillCacheGUIFromCacheManager()
  684. {
  685. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  686. cmCacheManager::CacheIterator it = cachem->NewIterator();
  687. size_t size = m_CacheEntriesList.GetItems().size();
  688. // if there are already entries in the cache, then
  689. // put the new ones in the top, so they show up first
  690. bool reverseOrder = false;
  691. // all the current values are not new any more
  692. std::set<CPropertyItem*> items = m_CacheEntriesList.GetItems();
  693. for(std::set<CPropertyItem*>::iterator i = items.begin();
  694. i != items.end(); ++i)
  695. {
  696. // first check to see if it is still in the cache
  697. CPropertyItem* item = *i;
  698. if ( !it.Find((const char*)item->m_propName) )
  699. {
  700. m_CacheEntriesList.RemoveProperty((const char*)item->m_propName);
  701. }
  702. else
  703. {
  704. // if it is still in the cache then it is no longer new
  705. item->m_NewValue = false;
  706. }
  707. }
  708. for(cmCacheManager::CacheIterator i = cachem->NewIterator();
  709. !i.IsAtEnd(); i.Next())
  710. {
  711. const char* key = i.GetName();
  712. // if value has trailing space or tab, enclose it in single quotes
  713. // to enforce the fact that it has 'invisible' trailing stuff
  714. std::string value = i.GetValue();
  715. if (value.size() &&
  716. (value[value.size() - 1] == ' ' ||
  717. value[value.size() - 1] == '\t'))
  718. {
  719. value = '\'' + value + '\'';
  720. }
  721. bool advanced = i.GetPropertyAsBool("ADVANCED");
  722. switch(i.GetType() )
  723. {
  724. case cmCacheManager::BOOL:
  725. if(cmSystemTools::IsOn(value.c_str()))
  726. {
  727. m_CacheEntriesList.AddProperty(key,
  728. "ON",
  729. i.GetProperty("HELPSTRING"),
  730. CPropertyList::COMBO,"ON|OFF",
  731. reverseOrder,
  732. advanced
  733. );
  734. }
  735. else
  736. {
  737. m_CacheEntriesList.AddProperty(key,
  738. "OFF",
  739. i.GetProperty("HELPSTRING"),
  740. CPropertyList::COMBO,"ON|OFF",
  741. reverseOrder, advanced
  742. );
  743. }
  744. break;
  745. case cmCacheManager::PATH:
  746. m_CacheEntriesList.AddProperty(key,
  747. value.c_str(),
  748. i.GetProperty("HELPSTRING"),
  749. CPropertyList::PATH,"",
  750. reverseOrder, advanced
  751. );
  752. break;
  753. case cmCacheManager::FILEPATH:
  754. m_CacheEntriesList.AddProperty(key,
  755. value.c_str(),
  756. i.GetProperty("HELPSTRING"),
  757. CPropertyList::FILE,"",
  758. reverseOrder, advanced
  759. );
  760. break;
  761. case cmCacheManager::STRING:
  762. m_CacheEntriesList.AddProperty(key,
  763. value.c_str(),
  764. i.GetProperty("HELPSTRING"),
  765. CPropertyList::EDIT,"",
  766. reverseOrder, advanced
  767. );
  768. break;
  769. case cmCacheManager::INTERNAL:
  770. m_CacheEntriesList.RemoveProperty(key);
  771. break;
  772. }
  773. }
  774. if(m_CacheEntriesList.GetShowAdvanced())
  775. {
  776. m_CacheEntriesList.ShowAdvanced();
  777. }
  778. else
  779. {
  780. m_CacheEntriesList.HideAdvanced();
  781. }
  782. m_OKButton.EnableWindow(false);
  783. if(cachem->GetSize() > 0 && !cmSystemTools::GetErrorOccuredFlag())
  784. {
  785. bool enable = true;
  786. items = m_CacheEntriesList.GetItems();
  787. for(std::set<CPropertyItem*>::iterator i = items.begin();
  788. i != items.end(); ++i)
  789. {
  790. CPropertyItem* item = *i;
  791. if(item->m_Advanced )
  792. {
  793. if(item->m_NewValue && m_CacheEntriesList.GetShowAdvanced())
  794. {
  795. enable = false;
  796. break;
  797. }
  798. }
  799. else
  800. {
  801. if(item->m_NewValue)
  802. {
  803. // if one new value then disable to OK button
  804. enable = false;
  805. break;
  806. }
  807. }
  808. }
  809. if(enable)
  810. {
  811. m_OKButton.EnableWindow(true);
  812. }
  813. }
  814. // redraw the list
  815. m_CacheEntriesList.SetTopIndex(0);
  816. m_CacheEntriesList.Invalidate();
  817. }
  818. // copy from the list box to the cache manager
  819. void CMakeSetupDialog::FillCacheManagerFromCacheGUI()
  820. {
  821. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  822. std::set<CPropertyItem*> items = m_CacheEntriesList.GetItems();
  823. cmCacheManager::CacheIterator it = cachem->NewIterator();
  824. for(std::set<CPropertyItem*>::iterator i = items.begin();
  825. i != items.end(); ++i)
  826. {
  827. CPropertyItem* item = *i;
  828. if ( it.Find((const char*)item->m_propName) )
  829. {
  830. // if value is enclosed in single quotes ('foo') then remove them
  831. // they were used to enforce the fact that it had 'invisible'
  832. // trailing stuff
  833. if (item->m_curValue.GetLength() >= 2 &&
  834. item->m_curValue[0] == '\'' &&
  835. item->m_curValue[item->m_curValue.GetLength() - 1] == '\'')
  836. {
  837. it.SetValue(item->m_curValue.Mid(
  838. 1, item->m_curValue.GetLength() - 2));
  839. }
  840. else
  841. {
  842. it.SetValue(item->m_curValue);
  843. }
  844. }
  845. }
  846. }
  847. //! Load cache file from m_WhereBuild and display in GUI editor
  848. void CMakeSetupDialog::LoadCacheFromDiskToGUI()
  849. {
  850. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  851. if(m_WhereBuild != "")
  852. {
  853. cachem->LoadCache(m_WhereBuild);
  854. this->FillCacheGUIFromCacheManager();
  855. cmCacheManager::CacheIterator it =
  856. cachem->GetCacheIterator("CMAKE_GENERATOR");
  857. if(!it.IsAtEnd())
  858. {
  859. std::string curGen = it.GetValue();
  860. if(m_GeneratorChoiceString != curGen.c_str())
  861. {
  862. m_GeneratorChoiceString = curGen.c_str();
  863. this->UpdateData(FALSE);
  864. }
  865. }
  866. }
  867. }
  868. //! Save GUI values to cmCacheManager and then save to disk.
  869. void CMakeSetupDialog::SaveCacheFromGUI()
  870. {
  871. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  872. this->FillCacheManagerFromCacheGUI();
  873. if(m_WhereBuild != "")
  874. {
  875. cachem->SaveCache(m_WhereBuild);
  876. }
  877. }
  878. void CMakeSetupDialog::OnSize(UINT nType, int cx, int cy)
  879. {
  880. if (nType == SIZE_MINIMIZED)
  881. {
  882. CDialog::OnSize(nType, cx, cy);
  883. return;
  884. }
  885. if (m_oldCX == -1)
  886. {
  887. m_oldCX = cx;
  888. m_oldCY = cy;
  889. }
  890. int deltax = cx - m_oldCX;
  891. int deltay = cy - m_oldCY;
  892. m_oldCX = cx;
  893. m_oldCY = cy;
  894. CDialog::OnSize(nType, cx, cy);
  895. if (deltax == 0 && deltay == 0)
  896. {
  897. return;
  898. }
  899. if(m_CacheEntriesList.m_hWnd)
  900. {
  901. // get the original sizes/positions
  902. CRect cRect;
  903. m_AdvancedValuesControl.GetWindowRect(&cRect);
  904. this->ScreenToClient(&cRect);
  905. m_AdvancedValuesControl.SetWindowPos(&wndTop, cRect.left + deltax,
  906. cRect.top,
  907. 0, 0,
  908. SWP_NOCOPYBITS |
  909. SWP_NOSIZE | SWP_NOZORDER);
  910. m_BuildForLabel.GetWindowRect(&cRect);
  911. this->ScreenToClient(&cRect);
  912. m_BuildForLabel.SetWindowPos(&wndTop, cRect.left + deltax,
  913. cRect.top,
  914. 0, 0,
  915. SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOZORDER);
  916. m_GeneratorChoice.GetWindowRect(&cRect);
  917. this->ScreenToClient(&cRect);
  918. m_GeneratorChoice.SetWindowPos(&wndTop, cRect.left + deltax,
  919. cRect.top,
  920. 0, 0,
  921. SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOZORDER);
  922. m_BrowseSource.GetWindowRect(&cRect);
  923. this->ScreenToClient(&cRect);
  924. m_BrowseSource.SetWindowPos(&wndTop, cRect.left + deltax,
  925. cRect.top,
  926. 0, 0,
  927. SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOZORDER);
  928. m_BrowseBuild.GetWindowRect(&cRect);
  929. this->ScreenToClient(&cRect);
  930. m_BrowseBuild.SetWindowPos(&wndTop, cRect.left + deltax,
  931. cRect.top,
  932. 0, 0,
  933. SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOZORDER);
  934. m_WhereSourceControl.GetWindowRect(&cRect);
  935. m_WhereSourceControl.SetWindowPos(&wndTop, cRect.left, cRect.top,
  936. cRect.Width() + deltax,
  937. cRect.Height(),
  938. SWP_NOCOPYBITS |
  939. SWP_NOMOVE | SWP_NOZORDER);
  940. m_WhereBuildControl.GetWindowRect(&cRect);
  941. m_WhereBuildControl.SetWindowPos(&wndTop, cRect.left, cRect.top,
  942. cRect.Width() + deltax,
  943. cRect.Height(),
  944. SWP_NOCOPYBITS |
  945. SWP_NOMOVE | SWP_NOZORDER);
  946. m_ListFrame.GetWindowRect(&cRect);
  947. m_ListFrame.SetWindowPos(&wndTop, cRect.left, cRect.top,
  948. cRect.Width() + deltax,
  949. cRect.Height() + deltay,
  950. SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
  951. m_CacheEntriesList.GetWindowRect(&cRect);
  952. m_CacheEntriesList.SetWindowPos(&wndTop, cRect.left, cRect.top,
  953. cRect.Width() + deltax,
  954. cRect.Height() + deltay,
  955. SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
  956. m_StatusDisplay.GetWindowRect(&cRect);
  957. this->ScreenToClient(&cRect);
  958. m_StatusDisplay.SetWindowPos(&wndBottom, cRect.left,
  959. cRect.top + deltay,
  960. cRect.Width() + deltax, cRect.Height(),
  961. SWP_NOCOPYBITS);
  962. m_MouseHelp.GetWindowRect(&cRect);
  963. this->ScreenToClient(&cRect);
  964. m_MouseHelp.SetWindowPos(&wndTop, cRect.left ,
  965. cRect.top + deltay,
  966. cRect.Width() + deltax, cRect.Height(),
  967. SWP_NOCOPYBITS | SWP_NOZORDER);
  968. deltax = int(deltax + m_deltaXRemainder);
  969. m_deltaXRemainder = float(deltax%2);
  970. m_Configure.GetWindowRect(&cRect);
  971. this->ScreenToClient(&cRect);
  972. m_Configure.SetWindowPos(&wndTop, cRect.left + deltax/2,
  973. cRect.top + deltay,
  974. 0, 0,
  975. SWP_NOCOPYBITS | SWP_NOSIZE);
  976. m_CancelButton.GetWindowRect(&cRect);
  977. this->ScreenToClient(&cRect);
  978. m_CancelButton.SetWindowPos(&wndTop, cRect.left + deltax/2,
  979. cRect.top + deltay,
  980. 0, 0,
  981. SWP_NOCOPYBITS | SWP_NOSIZE);
  982. m_OKButton.GetWindowRect(&cRect);
  983. this->ScreenToClient(&cRect);
  984. m_OKButton.SetWindowPos(&wndTop, cRect.left + deltax/2,
  985. cRect.top + deltay,
  986. 0, 0,
  987. SWP_NOCOPYBITS | SWP_NOSIZE);
  988. m_DeleteButton.GetWindowRect(&cRect);
  989. this->ScreenToClient(&cRect);
  990. m_DeleteButton.SetWindowPos(&wndTop, cRect.left + deltax/2,
  991. cRect.top + deltay,
  992. 0, 0,
  993. SWP_NOCOPYBITS | SWP_NOSIZE);
  994. m_HelpButton.GetWindowRect(&cRect);
  995. this->ScreenToClient(&cRect);
  996. m_HelpButton.SetWindowPos(&wndTop, cRect.left + deltax/2,
  997. cRect.top + deltay,
  998. 0, 0,
  999. SWP_NOCOPYBITS | SWP_NOSIZE);
  1000. }
  1001. }
  1002. void CMakeSetupDialog::OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI )
  1003. {
  1004. lpMMI->ptMinTrackSize.x = 550;
  1005. lpMMI->ptMinTrackSize.y = 272;
  1006. }
  1007. void CMakeSetupDialog::OnCancel()
  1008. {
  1009. if(m_RunningConfigure)
  1010. {
  1011. if(MessageBox("You are in the middle of a Configure.\n"
  1012. "If you Cancel now the configure information will be lost.\n"
  1013. "Are you sure you want to Cancel?", "Confirm Exit",
  1014. MB_YESNO) == IDYES)
  1015. {
  1016. cmSystemTools::SetFatalErrorOccured();
  1017. }
  1018. return;
  1019. }
  1020. if(m_CacheEntriesList.IsDirty())
  1021. {
  1022. if(MessageBox("You have changed options but not rebuilt, "
  1023. "are you sure you want to exit?", "Confirm Exit",
  1024. MB_YESNO) == IDYES)
  1025. {
  1026. CDialog::OnOK();
  1027. }
  1028. }
  1029. else
  1030. {
  1031. CDialog::OnOK();
  1032. }
  1033. }
  1034. void CMakeSetupDialog::OnOk()
  1035. {
  1036. // enable error messages each time configure is pressed
  1037. cmSystemTools::EnableMessages();
  1038. m_CacheEntriesList.ClearDirty();
  1039. this->RunCMake(true);
  1040. if (!(::GetKeyState(VK_SHIFT) & 0x1000))
  1041. {
  1042. CDialog::OnOK();
  1043. }
  1044. }
  1045. void CMakeSetupDialog::OnEditchangeGenerator()
  1046. {
  1047. // TODO: Add your control notification handler code here
  1048. }
  1049. // Create a shortcut on the desktop with the current Source/Build dir.
  1050. int CMakeSetupDialog::CreateShortcut()
  1051. {
  1052. // Find the desktop folder and create the link name
  1053. HKEY hKey;
  1054. if(RegOpenKeyEx(HKEY_CURRENT_USER,
  1055. "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
  1056. 0, KEY_READ, &hKey) != ERROR_SUCCESS)
  1057. {
  1058. AfxMessageBox ("Create shortcut: unable to find 'Shell Folders' key in registry!");
  1059. return 1;
  1060. }
  1061. DWORD dwType, dwSize;
  1062. #define MAXPATH 1024
  1063. char link_name[MAXPATH];
  1064. dwSize = MAXPATH;
  1065. if(RegQueryValueEx(hKey,
  1066. (LPCTSTR)"Desktop",
  1067. NULL,
  1068. &dwType,
  1069. (BYTE *)link_name,
  1070. &dwSize) != ERROR_SUCCESS)
  1071. {
  1072. AfxMessageBox ("Create shortcut: unable to find 'Desktop' registry value in 'Shell Folders' key!");
  1073. return 1;
  1074. }
  1075. if(dwType != REG_SZ)
  1076. {
  1077. AfxMessageBox ("Create shortcut: 'Desktop' registry value in 'Shell Folders' key has wrong type!");
  1078. return 1;
  1079. }
  1080. strcat(link_name, "\\CMake - ");
  1081. std::string current_dir = cmSystemTools::GetFilenameName((LPCTSTR)m_WhereSource);
  1082. strcat(link_name, current_dir.c_str());
  1083. strcat(link_name, ".lnk");
  1084. // Find the path to the current executable
  1085. char path_to_current_exe[MAXPATH];
  1086. ::GetModuleFileName(NULL, path_to_current_exe, MAXPATH);
  1087. // Create the shortcut
  1088. HRESULT hres;
  1089. IShellLink *psl;
  1090. // Initialize the COM library
  1091. hres = CoInitialize(NULL);
  1092. if (! SUCCEEDED (hres))
  1093. {
  1094. AfxMessageBox ("Create shortcut: unable to initialize the COM library!");
  1095. return 1;
  1096. }
  1097. // Create an IShellLink object and get a pointer to the IShellLink
  1098. // interface (returned from CoCreateInstance).
  1099. hres = CoCreateInstance(CLSID_ShellLink,
  1100. NULL,
  1101. CLSCTX_INPROC_SERVER,
  1102. IID_IShellLink,
  1103. (void **)&psl);
  1104. if (! SUCCEEDED (hres))
  1105. {
  1106. AfxMessageBox ("Create shortcut: unable to create IShellLink instance!");
  1107. return 1;
  1108. }
  1109. IPersistFile *ppf;
  1110. // Query IShellLink for the IPersistFile interface for
  1111. // saving the shortcut in persistent storage.
  1112. hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
  1113. if (SUCCEEDED (hres))
  1114. {
  1115. // Set the path to the shortcut target.
  1116. hres = psl->SetPath(path_to_current_exe);
  1117. if (! SUCCEEDED (hres))
  1118. {
  1119. AfxMessageBox ("Create shortcut: SetPath failed!");
  1120. }
  1121. // Set the arguments of the shortcut.
  1122. CString args = " /H=\"" + m_WhereSource + "\" /B=\"" + m_WhereBuild + "\" /G=\"" + m_GeneratorChoiceString + "\" /A=\"" + (m_AdvancedValues ? "TRUE" : "FALSE") + "\"";
  1123. hres = psl->SetArguments(args);
  1124. if (! SUCCEEDED (hres))
  1125. {
  1126. AfxMessageBox ("Create shortcut: SetArguments failed!");
  1127. }
  1128. // Set the description of the shortcut.
  1129. hres = psl->SetDescription("Shortcut to CMakeSetup");
  1130. if (! SUCCEEDED (hres))
  1131. {
  1132. AfxMessageBox ("Create shortcut: SetDescription failed!");
  1133. }
  1134. // Ensure that the string consists of ANSI characters.
  1135. WORD wsz[MAX_PATH];
  1136. MultiByteToWideChar(CP_ACP, 0, link_name, -1, wsz, MAX_PATH);
  1137. // Save the shortcut via the IPersistFile::Save member function.
  1138. hres = ppf->Save(wsz, TRUE);
  1139. if (! SUCCEEDED (hres))
  1140. {
  1141. AfxMessageBox ("Create shortcut: Save failed!");
  1142. }
  1143. // Release the pointer to IPersistFile.
  1144. ppf->Release ();
  1145. }
  1146. // Release the pointer to IShellLink.
  1147. psl->Release ();
  1148. return 0;
  1149. }
  1150. void CMakeSetupDialog::OnHelpButton()
  1151. {
  1152. CMakeHelp dialog;
  1153. dialog.DoModal();
  1154. }
  1155. void CMakeSetupDialog::OnDeleteButton()
  1156. {
  1157. if(m_WhereBuild != "" && this->m_CMakeInstance)
  1158. {
  1159. this->m_CMakeInstance->GetCacheManager()->DeleteCache(m_WhereBuild);
  1160. }
  1161. // Make sure we are working from the cache on disk
  1162. this->LoadCacheFromDiskToGUI();
  1163. m_OKButton.EnableWindow(false);
  1164. }
  1165. void CMakeSetupDialog::ShowAdvancedValues()
  1166. {
  1167. m_CacheEntriesList.ShowAdvanced();
  1168. }
  1169. void CMakeSetupDialog::RemoveAdvancedValues()
  1170. {
  1171. m_CacheEntriesList.HideAdvanced();
  1172. }
  1173. void CMakeSetupDialog::OnAdvancedValues()
  1174. {
  1175. this->UpdateData();
  1176. if(m_AdvancedValues)
  1177. {
  1178. this->ShowAdvancedValues();
  1179. }
  1180. else
  1181. {
  1182. this->RemoveAdvancedValues();
  1183. }
  1184. }
  1185. void CMakeSetupDialog::OnDoubleclickedAdvancedValues()
  1186. {
  1187. this->OnAdvancedValues();
  1188. }
  1189. // Handle param or single dropped file.
  1190. void CMakeSetupDialog::ChangeDirectoriesFromFile(const char* arg)
  1191. {
  1192. // Check if the argument refers to a CMakeCache.txt or
  1193. // CMakeLists.txt file.
  1194. std::string listPath;
  1195. std::string cachePath;
  1196. bool argIsFile = false;
  1197. if(cmSystemTools::FileIsDirectory(arg))
  1198. {
  1199. std::string path = cmSystemTools::CollapseFullPath(arg);
  1200. cmSystemTools::ConvertToUnixSlashes(path);
  1201. std::string cacheFile = path;
  1202. cacheFile += "/CMakeCache.txt";
  1203. std::string listFile = path;
  1204. listFile += "/CMakeLists.txt";
  1205. if(cmSystemTools::FileExists(cacheFile.c_str()))
  1206. {
  1207. cachePath = path;
  1208. }
  1209. if(cmSystemTools::FileExists(listFile.c_str()))
  1210. {
  1211. listPath = path;
  1212. }
  1213. }
  1214. else if(cmSystemTools::FileExists(arg))
  1215. {
  1216. argIsFile = true;
  1217. std::string fullPath = cmSystemTools::CollapseFullPath(arg);
  1218. std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
  1219. name = cmSystemTools::LowerCase(name);
  1220. if(name == "cmakecache.txt")
  1221. {
  1222. cachePath = cmSystemTools::GetFilenamePath(fullPath.c_str());
  1223. }
  1224. else if(name == "cmakelists.txt")
  1225. {
  1226. listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
  1227. }
  1228. }
  1229. // If there is a CMakeCache.txt file, use its settings.
  1230. if(cachePath.length() > 0)
  1231. {
  1232. cmCacheManager* cachem = m_CMakeInstance->GetCacheManager();
  1233. cmCacheManager::CacheIterator it = cachem->NewIterator();
  1234. if(cachem->LoadCache(cachePath.c_str()) && it.Find("CMAKE_HOME_DIRECTORY"))
  1235. {
  1236. std::string path = ConvertToWindowsPath(cachePath.c_str());
  1237. m_WhereBuild = path.c_str();
  1238. path = ConvertToWindowsPath(it.GetValue());
  1239. m_WhereSource = path.c_str();
  1240. m_GeneratorChoiceString = _T("");
  1241. return;
  1242. }
  1243. }
  1244. // If there is a CMakeLists.txt file, use it as the source tree.
  1245. if(listPath.length() > 0)
  1246. {
  1247. std::string path = ConvertToWindowsPath(listPath.c_str());
  1248. m_WhereSource = path.c_str();
  1249. if(argIsFile)
  1250. {
  1251. // Source CMakeLists.txt file given. It was probably dropped
  1252. // onto the window or executable. Default to an in-source
  1253. // build.
  1254. m_WhereBuild = path.c_str();
  1255. }
  1256. else
  1257. {
  1258. // Source directory given on command line. Use current working
  1259. // directory as build tree.
  1260. std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  1261. path = ConvertToWindowsPath(cwd.c_str());
  1262. m_WhereBuild = path.c_str();
  1263. }
  1264. }
  1265. }
  1266. // The framework calls this member function when the user releases the
  1267. // left mouse button over a window that has registered itself as the
  1268. // recipient of dropped files.
  1269. void CMakeSetupDialog::OnDropFiles(HDROP hDropInfo)
  1270. {
  1271. UINT nb_files = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
  1272. if (nb_files > 0)
  1273. {
  1274. UINT buffer_size = DragQueryFile(hDropInfo, 0, NULL, 0);
  1275. char *buffer = new char [buffer_size + 1];
  1276. DragQueryFile(hDropInfo, 0, buffer, buffer_size + 1);
  1277. this->ChangeDirectoriesFromFile(buffer);
  1278. delete [] buffer;
  1279. this->m_WhereSourceControl.SetWindowText(this->m_WhereSource);
  1280. this->m_WhereBuildControl.SetWindowText(this->m_WhereBuild);
  1281. this->UpdateData(FALSE);
  1282. this->OnChangeWhereSource();
  1283. this->OnChangeWhereBuild();
  1284. }
  1285. DragFinish(hDropInfo);
  1286. }
  1287. BOOL CMakeSetupDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  1288. {
  1289. ::SetCursor(m_Cursor);
  1290. return true;
  1291. }