]> cygwin.com Git - cygwin-apps/setup.git/blob - desktop.cc
* CHANGES: Update.
[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 #if 0
22 static const char *cvsid =
23 "\n%%% $Id$\n";
24 #endif
25
26 #include "win32.h"
27 #include <shlobj.h>
28 #include "desktop.h"
29 #include "propsheet.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34
35 #include "resource.h"
36 #include "msg.h"
37 #include "state.h"
38 #include "dialog.h"
39 #include "mount.h"
40 #include "mklink2.h"
41 #include "package_db.h"
42 #include "package_meta.h"
43 #include "package_version.h"
44 #include "filemanip.h"
45 #include "io_stream.h"
46 #include "getopt++/BoolOption.h"
47 #include "PackageSpecification.h"
48 #include "LogFile.h"
49
50 static BoolOption NoShortcutsOption (false, 'n', "no-shortcuts", "Disable creation of desktop and start menu shortcuts");
51 static BoolOption NoStartMenuOption (false, 'N', "no-startmenu", "Disable creation of start menu shortcut");
52 static BoolOption NoDesktopOption (false, 'd', "no-desktop", "Disable creation of desktop shortcut");
53
54 /* Lines starting with '@' are conditionals - include 'N' for NT,
55 '5' for Win95, '8' for Win98, '*' for all, like this:
56 echo foo
57 @N8
58 echo NT or 98
59 @*
60 */
61
62 static std::string batname;
63 static std::string iconname;
64
65 static ControlAdjuster::ControlInfo DesktopControlsInfo[] = {
66 {IDC_DESKTOP_SEPARATOR, CP_STRETCH, CP_BOTTOM},
67 {IDC_STATUS, CP_LEFT, CP_BOTTOM},
68 {IDC_STATUS_HEADER, CP_LEFT, CP_BOTTOM},
69 {0, CP_LEFT, CP_TOP}
70 };
71
72 DesktopSetupPage::DesktopSetupPage ()
73 {
74 sizeProcessor.AddControlInfo (DesktopControlsInfo);
75 }
76
77 static void
78 make_link (const std::string& linkpath,
79 const std::string& title,
80 const std::string& target)
81 {
82 std::string fname = linkpath + "/" + title + ".lnk";
83
84 if (_access (fname.c_str(), 0) == 0)
85 return; /* already exists */
86
87 msg ("make_link %s, %s, %s\n",
88 fname.c_str(), title.c_str(), target.c_str());
89
90 io_stream::mkpath_p (PATH_TO_FILE, std::string ("file://") + fname);
91
92 std::string exepath;
93 std::string argbuf;
94
95 if (IsWindowsNT ())
96 {
97 exepath = target;
98 argbuf = " ";
99 }
100 else
101 {
102 char windir[MAX_PATH];
103
104 GetWindowsDirectory (windir, sizeof (windir));
105 exepath = std::string(windir) + "\\command.com";
106 argbuf = "/E:4096 /c " + target;
107 }
108
109 msg ("make_link_2 (%s, %s, %s, %s)",
110 exepath.c_str(), argbuf.c_str(),
111 iconname.c_str(), fname.c_str());
112 make_link_2 (exepath.c_str(), argbuf.c_str(),
113 iconname.c_str(), fname.c_str());
114 }
115
116 static void
117 start_menu (const std::string& title, const std::string& target)
118 {
119 LPITEMIDLIST id;
120 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
121 SHGetSpecialFolderLocation (NULL,
122 issystem ? CSIDL_COMMON_PROGRAMS :
123 CSIDL_PROGRAMS, &id);
124 char _path[MAX_PATH];
125 SHGetPathFromIDList (id, _path);
126 std::string path(_path);
127 // Win95 does not use common programs unless multiple users for Win95 is enabled
128 msg ("Program directory for program link: %s", path.c_str());
129 if (path.empty())
130 {
131 SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
132 SHGetPathFromIDList (id, _path);
133 path = _path;
134 msg ("Program directory for program link changed to: %s",
135 path.c_str());
136 }
137 // end of Win95 addition
138 path += "/Cygwin";
139 make_link (path, title, target);
140 }
141
142 static void
143 desktop_icon (const std::string& title, const std::string& target)
144 {
145 char path[MAX_PATH];
146 LPITEMIDLIST id;
147 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
148 //SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_DESKTOP : CSIDL_COMMON_DESKTOPDIRECTORY, &id);
149 SHGetSpecialFolderLocation (NULL,
150 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
151 CSIDL_DESKTOPDIRECTORY, &id);
152 SHGetPathFromIDList (id, path);
153 // following lines added because it appears Win95 does not use common programs
154 // unless it comes into play when multiple users for Win95 is enabled
155 msg ("Desktop directory for desktop link: %s", path);
156 if (strlen (path) == 0)
157 {
158 SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
159 SHGetPathFromIDList (id, path);
160 msg ("Desktop directory for deskop link changed to: %s", path);
161 }
162 // end of Win95 addition
163 make_link (path, title, target);
164 }
165
166 static void
167 make_cygwin_bat ()
168 {
169 batname = backslash (cygpath ("/Cygwin.bat"));
170
171 /* if the batch file exists, don't overwrite it */
172 if (_access (batname.c_str(), 0) == 0)
173 return;
174
175 FILE *bat = fopen (batname.c_str(), "wt");
176 if (!bat)
177 return;
178
179 fprintf (bat, "@echo off\n\n");
180
181 fprintf (bat, "%.2s\n", get_root_dir ().c_str());
182 fprintf (bat, "chdir %s\n\n",
183 replace(backslash(get_root_dir() + "/bin"), "%", "%%").c_str());
184
185 fprintf (bat, "bash --login -i\n");
186
187 fclose (bat);
188 }
189
190 static void
191 save_icon ()
192 {
193 iconname = backslash (cygpath ("/Cygwin.ico"));
194
195 HRSRC rsrc = FindResource (NULL, "CYGWIN.ICON", "FILE");
196 if (rsrc == NULL)
197 {
198 fatal ("FindResource failed");
199 }
200 HGLOBAL res = LoadResource (NULL, rsrc);
201 char *data = (char *) LockResource (res);
202 int len = SizeofResource (NULL, rsrc);
203
204 FILE *f = fopen (iconname.c_str(), "wb");
205 if (f)
206 {
207 fwrite (data, 1, len, f);
208 fclose (f);
209 }
210 }
211
212 static void
213 do_desktop_setup ()
214 {
215 save_icon ();
216
217 make_cygwin_bat ();
218
219 if (root_menu)
220 {
221 start_menu ("Cygwin Bash Shell", batname);
222 }
223
224 if (root_desktop)
225 {
226 desktop_icon ("Cygwin", batname);
227 }
228 }
229
230 static int da[] = { IDC_ROOT_DESKTOP, 0 };
231 static int ma[] = { IDC_ROOT_MENU, 0 };
232
233 static void
234 check_if_enable_next (HWND h)
235 {
236 EnableWindow (GetDlgItem (h, IDOK), 1);
237 }
238
239 extern LogFile * theLog;
240
241 static void
242 set_status (HWND h)
243 {
244 char buf[1000], fmt[1000];
245 if (LoadString (hinstance, exit_msg, fmt, sizeof (fmt)) > 0)
246 {
247 snprintf (buf, 1000, fmt, backslash(theLog->getFileName(LOG_BABBLE)).c_str());
248 eset(h, IDC_STATUS, buf);
249 }
250 }
251
252 static char *header_string = NULL;
253 static char *message_string = NULL;
254 static void
255 load_dialog (HWND h)
256 {
257 if (source == IDC_SOURCE_DOWNLOAD)
258 {
259 // Don't need the checkboxes
260 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), FALSE);
261 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), FALSE);
262 if (header_string == NULL)
263 header_string = eget (h, IDC_STATIC_HEADER_TITLE, header_string);
264 if (message_string == NULL)
265 message_string = eget (h, IDC_STATIC_HEADER, message_string);
266 eset (h, IDC_STATIC_HEADER_TITLE, "Installation complete");
267 eset (h, IDC_STATIC_HEADER, "Shows installation status in download-only mode.");
268 }
269 else
270 {
271 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), TRUE);
272 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), TRUE);
273 if (header_string != NULL)
274 eset (h, IDC_STATIC_HEADER_TITLE, header_string);
275 if (message_string != NULL)
276 eset (h, IDC_STATIC_HEADER, message_string);
277 rbset (h, da, root_desktop);
278 rbset (h, ma, root_menu);
279 }
280 check_if_enable_next (h);
281 set_status (h);
282 }
283
284 static int
285 check_desktop (const std::string title, const std::string target)
286 {
287 char path[MAX_PATH];
288 LPITEMIDLIST id;
289 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
290 SHGetSpecialFolderLocation (NULL,
291 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
292 CSIDL_DESKTOPDIRECTORY, &id);
293 SHGetPathFromIDList (id, path);
294 // following lines added because it appears Win95 does not use common programs
295 // unless it comes into play when multiple users for Win95 is enabled
296 msg ("Desktop directory for desktop link: %s", path);
297 if (strlen (path) == 0)
298 {
299 SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
300 SHGetPathFromIDList (id, path);
301 msg ("Desktop directory for deskop link changed to: %s", path);
302 }
303 // end of Win95 addition
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 fname = std::string(path) + "/" + title + ".pif"; /* check for a pif as well */
310
311 if (_access (fname.c_str(), 0) == 0)
312 return 0; /* already exists */
313
314 return IDC_ROOT_DESKTOP;
315 }
316
317 static int
318 check_startmenu (const std::string title, const std::string target)
319 {
320 char path[MAX_PATH];
321 LPITEMIDLIST id;
322 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
323 SHGetSpecialFolderLocation (NULL,
324 issystem ? CSIDL_COMMON_PROGRAMS :
325 CSIDL_PROGRAMS, &id);
326 SHGetPathFromIDList (id, path);
327 // following lines added because it appears Win95 does not use common programs
328 // unless it comes into play when multiple users for Win95 is enabled
329 msg ("Program directory for program link: %s", path);
330 if (strlen (path) == 0)
331 {
332 SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
333 SHGetPathFromIDList (id, path);
334 msg ("Program directory for program link changed to: %s", path);
335 }
336 // end of Win95 addition
337 strcat (path, "/Cygwin");
338 std::string fname = std::string(path) + "/" + title + ".lnk";
339
340 if (_access (fname.c_str(), 0) == 0)
341 return 0; /* already exists */
342
343 fname = std::string(path) + "/" + title + ".pif"; /* check for a pif as well */
344
345 if (_access (fname.c_str(), 0) == 0)
346 return 0; /* already exists */
347
348 return IDC_ROOT_MENU;
349 }
350
351 static void
352 save_dialog (HWND h)
353 {
354 root_desktop = rbget (h, da);
355 root_menu = rbget (h, ma);
356 }
357
358 static BOOL
359 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
360 {
361 switch (id)
362 {
363
364 case IDC_ROOT_DESKTOP:
365 case IDC_ROOT_MENU:
366 save_dialog (h);
367 check_if_enable_next (h);
368 break;
369 }
370 return 0;
371 }
372
373 bool
374 DesktopSetupPage::Create ()
375 {
376 return PropertyPage::Create (NULL, dialog_cmd, IDD_DESKTOP);
377 }
378
379 void
380 DesktopSetupPage::OnInit ()
381 {
382 // FIXME: This CoInitialize() feels like it could be moved to startup in main.cc.
383 CoInitialize (NULL);
384
385 SetDlgItemFont(IDC_STATUS_HEADER, "MS Shell Dlg", 8, FW_BOLD);
386 }
387
388 void
389 DesktopSetupPage::OnActivate ()
390 {
391 if (NoShortcutsOption || source == IDC_SOURCE_DOWNLOAD)
392 {
393 root_desktop = root_menu = 0;
394 }
395 else
396 {
397 if (NoStartMenuOption)
398 {
399 root_menu = 0;
400 }
401 else
402 {
403 root_menu =
404 check_startmenu ("Cygwin Bash Shell",
405 backslash (cygpath ("/cygwin.bat")));
406 }
407
408 if (NoDesktopOption)
409 {
410 root_desktop = 0;
411 }
412 else
413 {
414 root_desktop =
415 check_desktop ("Cygwin", backslash (cygpath ("/cygwin.bat")));
416 }
417 }
418
419 load_dialog (GetHWND ());
420 }
421
422 long
423 DesktopSetupPage::OnBack ()
424 {
425 HWND h = GetHWND ();
426 save_dialog (h);
427 return IDD_CHOOSE;
428 }
429
430 bool
431 DesktopSetupPage::OnFinish ()
432 {
433 HWND h = GetHWND ();
434 save_dialog (h);
435 if (source != IDC_SOURCE_DOWNLOAD)
436 do_desktop_setup ();
437
438 return true;
439 }
440
441 long
442 DesktopSetupPage::OnUnattended ()
443 {
444 Window::PostMessage (WM_APP_UNATTENDED_FINISH);
445 // GetOwner ()->PressButton(PSBTN_FINISH);
446 return -1;
447 }
448
449 bool
450 DesktopSetupPage::OnMessageApp (UINT uMsg, WPARAM wParam, LPARAM lParam)
451 {
452 switch (uMsg)
453 {
454 case WM_APP_UNATTENDED_FINISH:
455 {
456 GetOwner ()->PressButton(PSBTN_FINISH);
457 break;
458 }
459 default:
460 {
461 // Not handled
462 return false;
463 }
464 }
465
466 return true;
467 }
This page took 0.053921 seconds and 5 git commands to generate.