]> cygwin.com Git - cygwin-apps/setup.git/blob - desktop.cc
Use solver to check for problems and produce a list of package transactions
[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", "Disable creation of desktop and start menu shortcuts");
44 static BoolOption NoStartMenuOption (false, 'N', "no-startmenu", "Disable creation of start menu shortcut");
45 static BoolOption NoDesktopOption (false, 'd', "no-desktop", "Disable creation of desktop shortcut");
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 void
99 start_menu (const std::string& title, const std::string& target,
100 const std::string& arg, const std::string& iconpath)
101 {
102 /* Special folders always < MAX_PATH. */
103 char path[MAX_PATH];
104 LPITEMIDLIST id;
105 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
106 SHGetSpecialFolderLocation (NULL,
107 issystem ? CSIDL_COMMON_PROGRAMS :
108 CSIDL_PROGRAMS, &id);
109 SHGetPathFromIDList (id, path);
110 strncat (path, "/Cygwin", MAX_PATH);
111 LogBabblePrintf ("Program directory for program link: %s", path);
112 make_link (path, title, target, arg, iconpath);
113 }
114
115 static void
116 desktop_icon (const std::string& title, const std::string& target,
117 const std::string& arg, const std::string& iconpath)
118 {
119 /* Special folders always < MAX_PATH. */
120 char path[MAX_PATH];
121 LPITEMIDLIST id;
122 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
123 SHGetSpecialFolderLocation (NULL,
124 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
125 CSIDL_DESKTOPDIRECTORY, &id);
126 SHGetPathFromIDList (id, path);
127 LogBabblePrintf ("Desktop directory for desktop link: %s", path);
128 make_link (path, title, target, arg, iconpath);
129 }
130
131 static void
132 make_cygwin_bat ()
133 {
134 batname = backslash (cygpath ("/Cygwin.bat"));
135 FILE *bat;
136
137 size_t len = batname.size () + 7;
138 WCHAR wname[len];
139 mklongpath (wname, batname.c_str (), len);
140
141 /* if the batch file exists, don't overwrite it */
142 if (GetFileAttributesW (wname) != INVALID_FILE_ATTRIBUTES)
143 return;
144
145 bat = nt_wfopen (wname, "wt", 0755);
146
147 if (!bat)
148 return;
149
150 fprintf (bat, "@echo off\n\n");
151
152 fprintf (bat, "%.2s\n", get_root_dir ().c_str());
153 fprintf (bat, "chdir %s\n\n",
154 replace(backslash(get_root_dir() + "/bin"), "%", "%%").c_str());
155
156 fprintf (bat, "bash --login -i\n");
157
158 fclose (bat);
159 }
160
161 static void
162 save_icon (std::string &iconpath, const char *resource_name)
163 {
164 HRSRC rsrc = FindResource (NULL, resource_name, "FILE");
165 if (rsrc == NULL)
166 {
167 fatal ("FindResource failed");
168 }
169 HGLOBAL res = LoadResource (NULL, rsrc);
170 char *data = (char *) LockResource (res);
171 int len = SizeofResource (NULL, rsrc);
172
173 FILE *f;
174 WIN32_FILE_ATTRIBUTE_DATA attr;
175
176 size_t ilen = iconpath.size () + 7;
177 WCHAR wname[ilen];
178 mklongpath (wname, iconpath.c_str (), ilen);
179 if (GetFileAttributesExW (wname, GetFileExInfoStandard, &attr)
180 && attr.dwFileAttributes != INVALID_FILE_ATTRIBUTES
181 && attr.nFileSizeLow > 7022) /* Size of old icon */
182 return;
183
184 f = nt_wfopen (wname, "wb", 0644);
185 if (f)
186 {
187 fwrite (data, 1, len, f);
188 fclose (f);
189 }
190 }
191
192 #define TARGET "/bin/mintty"
193 #define DEFAULTICON "/Cygwin.ico"
194 #define TERMINALICON "/Cygwin-Terminal.ico"
195 #define TERMINALTITLE (is_64bit ? "Cygwin64 Terminal" \
196 : "Cygwin Terminal")
197 #define STARTMENUDIR "/Cygwin"
198
199 static void
200 do_desktop_setup ()
201 {
202 std::string target = backslash (cygpath (TARGET));
203 std::string defaulticon = backslash (cygpath (DEFAULTICON));
204 std::string terminalicon = backslash (cygpath (TERMINALICON));
205
206 save_icon (defaulticon, "CYGWIN.ICON");
207 save_icon (terminalicon, "CYGWIN-TERMINAL.ICON");
208
209 make_cygwin_bat ();
210
211 if (root_menu)
212 start_menu (TERMINALTITLE, target, "-i " TERMINALICON " -", terminalicon);
213
214 if (root_desktop)
215 desktop_icon (TERMINALTITLE, target, "-i " TERMINALICON " -", terminalicon);
216 }
217
218 static int da[] = { IDC_ROOT_DESKTOP, 0 };
219 static int ma[] = { IDC_ROOT_MENU, 0 };
220
221 static void
222 check_if_enable_next (HWND h)
223 {
224 EnableWindow (GetDlgItem (h, IDOK), 1);
225 }
226
227 static void
228 set_status (HWND h)
229 {
230 char buf[1000], fmt[1000];
231 if (LoadString (hinstance, Logger ().getExitMsg (), fmt, sizeof (fmt)) > 0)
232 {
233 snprintf (buf, 1000, fmt,
234 backslash (Logger ().getFileName (LOG_BABBLE)).c_str ());
235 eset (h, IDC_STATUS, buf);
236 }
237 }
238
239 static char *header_string = NULL;
240 static char *message_string = NULL;
241 static void
242 load_dialog (HWND h)
243 {
244 if (source == IDC_SOURCE_DOWNLOAD)
245 {
246 // Don't need the checkboxes
247 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), FALSE);
248 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), FALSE);
249 if (header_string == NULL)
250 header_string = eget (h, IDC_STATIC_HEADER_TITLE, header_string);
251 if (message_string == NULL)
252 message_string = eget (h, IDC_STATIC_HEADER, message_string);
253 eset (h, IDC_STATIC_HEADER_TITLE, "Installation complete");
254 eset (h, IDC_STATIC_HEADER, "Shows installation status in download-only mode.");
255 }
256 else
257 {
258 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), TRUE);
259 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), TRUE);
260 if (header_string != NULL)
261 eset (h, IDC_STATIC_HEADER_TITLE, header_string);
262 if (message_string != NULL)
263 eset (h, IDC_STATIC_HEADER, message_string);
264 rbset (h, da, root_desktop);
265 rbset (h, ma, root_menu);
266 }
267 check_if_enable_next (h);
268 set_status (h);
269 }
270
271 static int
272 check_desktop (const std::string title, const std::string target)
273 {
274 /* Special folders always < MAX_PATH. */
275 char path[MAX_PATH];
276 LPITEMIDLIST id;
277 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
278 SHGetSpecialFolderLocation (NULL,
279 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
280 CSIDL_DESKTOPDIRECTORY, &id);
281 SHGetPathFromIDList (id, path);
282 LogBabblePrintf ("Desktop directory for desktop link: %s", path);
283 std::string fname = std::string(path) + "/" + title + ".lnk";
284
285 if (_access (fname.c_str(), 0) == 0)
286 return 0; /* already exists */
287
288 return IDC_ROOT_DESKTOP;
289 }
290
291 static int
292 check_startmenu (const std::string title, const std::string target)
293 {
294 /* Special folders always < MAX_PATH. */
295 char path[MAX_PATH];
296 LPITEMIDLIST id;
297 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
298 SHGetSpecialFolderLocation (NULL,
299 issystem ? CSIDL_COMMON_PROGRAMS :
300 CSIDL_PROGRAMS, &id);
301 SHGetPathFromIDList (id, path);
302 LogBabblePrintf ("Program directory for program link: %s", path);
303 strcat (path, STARTMENUDIR);
304 std::string fname = std::string(path) + "/" + title + ".lnk";
305
306 if (_access (fname.c_str(), 0) == 0)
307 return 0; /* already exists */
308
309 return IDC_ROOT_MENU;
310 }
311
312 static void
313 save_dialog (HWND h)
314 {
315 root_desktop = rbget (h, da);
316 root_menu = rbget (h, ma);
317 }
318
319 static BOOL
320 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
321 {
322 switch (id)
323 {
324
325 case IDC_ROOT_DESKTOP:
326 case IDC_ROOT_MENU:
327 save_dialog (h);
328 check_if_enable_next (h);
329 break;
330 }
331 return 0;
332 }
333
334 bool
335 DesktopSetupPage::Create ()
336 {
337 return PropertyPage::Create (NULL, dialog_cmd, IDD_DESKTOP);
338 }
339
340 void
341 DesktopSetupPage::OnInit ()
342 {
343 SetDlgItemFont(IDC_STATUS_HEADER, "MS Shell Dlg", 8, FW_BOLD);
344 }
345
346 void
347 DesktopSetupPage::OnActivate ()
348 {
349 if (NoShortcutsOption || source == IDC_SOURCE_DOWNLOAD)
350 {
351 root_desktop = root_menu = 0;
352 }
353 else
354 {
355 std::string target = backslash (cygpath (TARGET));
356
357 if (NoStartMenuOption)
358 {
359 root_menu = 0;
360 }
361 else
362 {
363 root_menu = check_startmenu (TERMINALTITLE, target);
364 }
365
366 if (NoDesktopOption)
367 {
368 root_desktop = 0;
369 }
370 else
371 {
372 root_desktop = check_desktop (TERMINALTITLE, target);
373 }
374 }
375
376 load_dialog (GetHWND ());
377 }
378
379 long
380 DesktopSetupPage::OnBack ()
381 {
382 HWND h = GetHWND ();
383 save_dialog (h);
384 return IDD_CHOOSE;
385 }
386
387 bool
388 DesktopSetupPage::OnFinish ()
389 {
390 HWND h = GetHWND ();
391 save_dialog (h);
392 if (source != IDC_SOURCE_DOWNLOAD)
393 do_desktop_setup ();
394
395 return true;
396 }
397
398 long
399 DesktopSetupPage::OnUnattended ()
400 {
401 Window::PostMessageNow (WM_APP_UNATTENDED_FINISH);
402 // GetOwner ()->PressButton(PSBTN_FINISH);
403 return -1;
404 }
405
406 bool
407 DesktopSetupPage::OnMessageApp (UINT uMsg, WPARAM wParam, LPARAM lParam)
408 {
409 switch (uMsg)
410 {
411 case WM_APP_UNATTENDED_FINISH:
412 {
413 GetOwner ()->PressButton(PSBTN_FINISH);
414 break;
415 }
416 default:
417 {
418 // Not handled
419 return false;
420 }
421 }
422
423 return true;
424 }
This page took 0.055171 seconds and 5 git commands to generate.