]> cygwin.com Git - cygwin-apps/setup.git/blob - desktop.cc
Suppress bogus free-nonheap-object warning in iniparse.cc
[cygwin-apps/setup.git] / desktop.cc
1 /*
2 * Copyright (c) 2000, 2001 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16 /* The purpose of this file is to manage all the desktop setup, such
17 as start menu, batch files, desktop icons, and shortcuts. Note
18 that unlike other do_* functions, this one is called directly from
19 install.cc */
20
21 #include "win32.h"
22 #include <shlobj.h>
23 #include "desktop.h"
24 #include "propsheet.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29
30 #include "ini.h"
31 #include "resource.h"
32 #include "state.h"
33 #include "dialog.h"
34 #include "mount.h"
35 #include "mklink2.h"
36 #include "package_db.h"
37 #include "package_meta.h"
38 #include "filemanip.h"
39 #include "io_stream.h"
40 #include "getopt++/BoolOption.h"
41 #include "LogFile.h"
42
43 static BoolOption NoShortcutsOption (false, 'n', "no-shortcuts", IDS_HELPTEXT_NO_SHORTCUTS);
44 static BoolOption NoStartMenuOption (false, 'N', "no-startmenu", IDS_HELPTEXT_NO_STARTMENU);
45 static BoolOption NoDesktopOption (false, 'd', "no-desktop", IDS_HELPTEXT_NO_DESKTOP);
46
47 /* Lines starting with '@' are conditionals - include 'N' for NT,
48 '5' for Win95, '8' for Win98, '*' for all, like this:
49 echo foo
50 @N8
51 echo NT or 98
52 @*
53 */
54
55 static std::string batname;
56 static ControlAdjuster::ControlInfo DesktopControlsInfo[] = {
57 {IDC_DESKTOP_SEPARATOR, CP_STRETCH, CP_BOTTOM},
58 {IDC_STATUS, CP_LEFT, CP_BOTTOM},
59 {IDC_STATUS_HEADER, CP_LEFT, CP_BOTTOM},
60 {0, CP_LEFT, CP_TOP}
61 };
62
63 DesktopSetupPage::DesktopSetupPage ()
64 {
65 sizeProcessor.AddControlInfo (DesktopControlsInfo);
66 }
67
68 static void
69 make_link (const std::string& linkpath,
70 const std::string& title,
71 const std::string& target,
72 const std::string& arg,
73 const std::string& icon)
74 {
75 std::string fname = linkpath + "/" + title + ".lnk";
76
77 if (_access (fname.c_str(), 0) == 0)
78 return; /* already exists */
79
80 LogBabblePrintf ("make_link %s, %s, %s\n",
81 fname.c_str(), title.c_str(), target.c_str());
82
83 io_stream::mkpath_p (PATH_TO_FILE, std::string ("file://") + fname, 0);
84
85 std::string exepath;
86 std::string argbuf;
87
88 exepath = target;
89 argbuf = arg;
90
91 LogBabblePrintf ("make_link_2 (%s, %s, %s, %s)",
92 exepath.c_str(), argbuf.c_str(),
93 icon.c_str(), fname.c_str());
94 make_link_2 (exepath.c_str(), argbuf.c_str(),
95 icon.c_str(), fname.c_str());
96 }
97
98 static const char *startmenudir()
99 {
100 if (!is_64bit && (WowNativeMachine() != IMAGE_FILE_MACHINE_I386))
101 return "/Cygwin (32-bit)";
102 else
103 return "/Cygwin";
104 }
105
106 static void
107 start_menu (const std::string& title, const std::string& target,
108 const std::string& arg, const std::string& iconpath)
109 {
110 /* Special folders always < MAX_PATH. */
111 char path[MAX_PATH];
112 LPITEMIDLIST id;
113 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
114 SHGetSpecialFolderLocation (NULL,
115 issystem ? CSIDL_COMMON_PROGRAMS :
116 CSIDL_PROGRAMS, &id);
117 SHGetPathFromIDList (id, path);
118 strncat (path, startmenudir(), MAX_PATH - strlen(path) - 1);
119 LogBabblePrintf ("Program directory for program link: %s", path);
120 make_link (path, title, target, arg, iconpath);
121 }
122
123 static void
124 desktop_icon (const std::string& title, const std::string& target,
125 const std::string& arg, const std::string& iconpath)
126 {
127 /* Special folders always < MAX_PATH. */
128 char path[MAX_PATH];
129 LPITEMIDLIST id;
130 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
131 SHGetSpecialFolderLocation (NULL,
132 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
133 CSIDL_DESKTOPDIRECTORY, &id);
134 SHGetPathFromIDList (id, path);
135 LogBabblePrintf ("Desktop directory for desktop link: %s", path);
136 make_link (path, title, target, arg, iconpath);
137 }
138
139 static void
140 make_cygwin_bat ()
141 {
142 batname = backslash (cygpath ("/Cygwin.bat"));
143 FILE *bat;
144
145 size_t len = batname.size () + 7;
146 WCHAR wname[len];
147 mklongpath (wname, batname.c_str (), len);
148
149 /* if the batch file exists, don't overwrite it */
150 if (GetFileAttributesW (wname) != INVALID_FILE_ATTRIBUTES)
151 return;
152
153 bat = nt_wfopen (wname, "wt", 0755);
154
155 if (!bat)
156 return;
157
158 fprintf (bat, "@echo off\n\n");
159
160 fprintf (bat, "%.2s\n", get_root_dir ().c_str());
161 fprintf (bat, "chdir %s\n\n",
162 replace(backslash(get_root_dir() + "/bin"), "%", "%%").c_str());
163
164 fprintf (bat, "bash --login -i\n");
165
166 fclose (bat);
167 }
168
169 static void
170 save_icon (std::string &iconpath, const char *resource_name)
171 {
172 HRSRC rsrc = FindResource (NULL, resource_name, "FILE");
173 if (rsrc == NULL)
174 {
175 Log (LOG_PLAIN) << "FindResource failed" << GetLastError() << endLog;
176 return;
177 }
178
179 HGLOBAL res = LoadResource (NULL, rsrc);
180 char *data = (char *) LockResource (res);
181 int len = SizeofResource (NULL, rsrc);
182
183 FILE *f;
184 WIN32_FILE_ATTRIBUTE_DATA attr;
185
186 size_t ilen = iconpath.size () + 7;
187 WCHAR wname[ilen];
188 mklongpath (wname, iconpath.c_str (), ilen);
189 if (GetFileAttributesExW (wname, GetFileExInfoStandard, &attr)
190 && attr.dwFileAttributes != INVALID_FILE_ATTRIBUTES
191 && attr.nFileSizeLow > 7022) /* Size of old icon */
192 return;
193
194 f = nt_wfopen (wname, "wb", 0644);
195 if (f)
196 {
197 fwrite (data, 1, len, f);
198 fclose (f);
199 }
200 }
201
202 #define TARGET "/bin/mintty"
203 #define DEFAULTICON "/Cygwin.ico"
204 #define TERMINALICON "/Cygwin-Terminal.ico"
205 #define TERMINALTITLE (is_64bit ? "Cygwin64 Terminal" \
206 : "Cygwin Terminal")
207
208 static void
209 do_desktop_setup ()
210 {
211 std::string target = backslash (cygpath (TARGET));
212 std::string defaulticon = backslash (cygpath (DEFAULTICON));
213 std::string terminalicon = backslash (cygpath (TERMINALICON));
214
215 save_icon (defaulticon, "CYGWIN.ICON");
216 save_icon (terminalicon, "CYGWIN-TERMINAL.ICON");
217
218 make_cygwin_bat ();
219
220 if (root_menu)
221 start_menu (TERMINALTITLE, target, "-i " TERMINALICON " -", terminalicon);
222
223 if (root_desktop)
224 desktop_icon (TERMINALTITLE, target, "-i " TERMINALICON " -", terminalicon);
225 }
226
227 static int da[] = { IDC_ROOT_DESKTOP, 0 };
228 static int ma[] = { IDC_ROOT_MENU, 0 };
229
230 static void
231 check_if_enable_next (HWND h)
232 {
233 EnableWindow (GetDlgItem (h, IDOK), 1);
234 }
235
236 static void
237 set_status (HWND h)
238 {
239 std::wstring fmt = LoadStringW(Logger ().getExitMsg ());
240 std::wstring buf = format(fmt, backslash (Logger ().getFileName (LOG_BABBLE)).c_str ());
241 eset (h, IDC_STATUS, buf);
242 }
243
244 static void
245 load_dialog (HWND h)
246 {
247 if (source == IDC_SOURCE_DOWNLOAD)
248 {
249 // Don't need the checkboxes
250 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), FALSE);
251 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), FALSE);
252 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_DOWNLOAD), SW_SHOW);
253 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_DOWNLOAD), SW_SHOW);
254 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_INSTALL), SW_HIDE);
255 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_INSTALL), SW_HIDE);
256 }
257 else
258 {
259 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), TRUE);
260 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), TRUE);
261 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_DOWNLOAD), SW_HIDE);
262 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_DOWNLOAD), SW_HIDE);
263 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_INSTALL), SW_SHOW);
264 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_INSTALL), SW_SHOW);
265 rbset (h, da, root_desktop);
266 rbset (h, ma, root_menu);
267 }
268 check_if_enable_next (h);
269 set_status (h);
270 }
271
272 static int
273 check_desktop (const std::string title, const std::string target)
274 {
275 /* Special folders always < MAX_PATH. */
276 char path[MAX_PATH];
277 LPITEMIDLIST id;
278 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
279 SHGetSpecialFolderLocation (NULL,
280 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
281 CSIDL_DESKTOPDIRECTORY, &id);
282 SHGetPathFromIDList (id, path);
283 LogBabblePrintf ("Desktop directory for desktop link: %s", path);
284 std::string fname = std::string(path) + "/" + title + ".lnk";
285
286 if (_access (fname.c_str(), 0) == 0)
287 return 0; /* already exists */
288
289 return IDC_ROOT_DESKTOP;
290 }
291
292 static int
293 check_startmenu (const std::string title, const std::string target)
294 {
295 /* Special folders always < MAX_PATH. */
296 char path[MAX_PATH];
297 LPITEMIDLIST id;
298 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
299 SHGetSpecialFolderLocation (NULL,
300 issystem ? CSIDL_COMMON_PROGRAMS :
301 CSIDL_PROGRAMS, &id);
302 SHGetPathFromIDList (id, path);
303 LogBabblePrintf ("Program directory for program link: %s", path);
304 strcat (path, startmenudir());
305 std::string fname = std::string(path) + "/" + title + ".lnk";
306
307 if (_access (fname.c_str(), 0) == 0)
308 return 0; /* already exists */
309
310 return IDC_ROOT_MENU;
311 }
312
313 static void
314 save_dialog (HWND h)
315 {
316 root_desktop = rbget (h, da);
317 root_menu = rbget (h, ma);
318 }
319
320 static BOOL
321 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
322 {
323 switch (id)
324 {
325
326 case IDC_ROOT_DESKTOP:
327 case IDC_ROOT_MENU:
328 save_dialog (h);
329 check_if_enable_next (h);
330 break;
331 }
332 return 0;
333 }
334
335 bool
336 DesktopSetupPage::Create ()
337 {
338 return PropertyPage::Create (NULL, dialog_cmd, IDD_DESKTOP);
339 }
340
341 void
342 DesktopSetupPage::OnInit ()
343 {
344 SetDlgItemFont(IDC_STATUS_HEADER, "MS Shell Dlg", 8, FW_BOLD);
345 }
346
347 void
348 DesktopSetupPage::OnActivate ()
349 {
350 if (NoShortcutsOption || source == IDC_SOURCE_DOWNLOAD)
351 {
352 root_desktop = root_menu = 0;
353 }
354 else
355 {
356 std::string target = backslash (cygpath (TARGET));
357
358 if (NoStartMenuOption)
359 {
360 root_menu = 0;
361 }
362 else
363 {
364 root_menu = check_startmenu (TERMINALTITLE, target);
365 }
366
367 if (NoDesktopOption)
368 {
369 root_desktop = 0;
370 }
371 else
372 {
373 root_desktop = check_desktop (TERMINALTITLE, target);
374 }
375 }
376
377 load_dialog (GetHWND ());
378 }
379
380 long
381 DesktopSetupPage::OnBack ()
382 {
383 HWND h = GetHWND ();
384 save_dialog (h);
385 return IDD_CHOOSE;
386 }
387
388 bool
389 DesktopSetupPage::OnFinish ()
390 {
391 HWND h = GetHWND ();
392 save_dialog (h);
393 if (source != IDC_SOURCE_DOWNLOAD)
394 do_desktop_setup ();
395
396 return true;
397 }
398
399 long
400 DesktopSetupPage::OnUnattended ()
401 {
402 Window::PostMessageNow (WM_APP_UNATTENDED_FINISH);
403 // GetOwner ()->PressButton(PSBTN_FINISH);
404 return -1;
405 }
406
407 bool
408 DesktopSetupPage::OnMessageApp (UINT uMsg, WPARAM wParam, LPARAM lParam)
409 {
410 switch (uMsg)
411 {
412 case WM_APP_UNATTENDED_FINISH:
413 {
414 GetOwner ()->PressButton(PSBTN_FINISH);
415 break;
416 }
417 default:
418 {
419 // Not handled
420 return false;
421 }
422 }
423
424 return true;
425 }
This page took 0.052732 seconds and 5 git commands to generate.