e5d4d4df5a6bdb1551e8029a87dea16332979f1c
[chise/xemacs-chise.git.1] / netinstall / desktop.cc
1 /*
2  * Copyright (c) 2000, 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
22 #include "win32.h"
23 #include <shlobj.h>
24
25 #include <io.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #ifndef WIN32_NATIVE
29 #include <unistd.h>
30 #endif
31
32 #include "resource.h"
33 #include "ini.h"
34 #include "msg.h"
35 #include "state.h"
36 #include "concat.h"
37 #include "mkdir.h"
38 #include "dialog.h"
39 #include "version.h"
40 #include "reginfo.h"
41 #include "regedit.h"
42 #include "port.h"
43 #include "log.h"
44
45 extern "C" {
46   void make_link_2 (char *exepath, char *args, char *icon, char *lname);
47 };
48
49 static OSVERSIONINFO verinfo;
50
51 /* Lines starting with '@' are conditionals - include 'N' for NT,
52    '5' for Win95, '8' for Win98, '*' for all, like this:
53         echo foo
54         @N8
55         echo NT or 98
56         @*
57    */
58
59 #define COMMAND9XARGS "/E:4096 /c"
60 #define COMMAND9XEXE  "\\command.com"
61
62 static char *iconname;
63 static char *batname;
64 static char *uninstname;
65
66 static void
67 make_link (char *linkpath, char *title, char *target, char* args)
68 {
69 #if 0
70   char argbuf[_MAX_PATH];
71 #endif
72   char *fname = concat (linkpath, "/", title, ".lnk", 0);
73
74   if (_access (fname, 0) == 0)
75     return; /* already exists */
76
77   msg ("make_link %s, %s, %s, %s\n", fname, title, target, args);
78
79   mkdir_p (0, fname);
80
81   char *exepath;
82 #if 0
83   /* If we are running Win9x, build a command line. */
84   if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
85     {
86 #endif
87       exepath = target;
88 #if 0
89     }
90   else
91     {
92       char windir[MAX_PATH];
93
94       GetWindowsDirectory (windir, sizeof (windir));
95       exepath = concat (windir, COMMAND9XEXE, 0);
96       sprintf (argbuf, "%s %s", COMMAND9XARGS, target);
97       args = argbuf;
98     }
99 #endif
100   msg ("make_link_2 (%s, %s, %s, %s)", exepath, args, iconname, fname);
101   make_link_2 (backslash (exepath), args, iconname, fname);
102 }
103
104 static char* 
105 find_xemacs_exe_path ()
106 {
107   if (xemacs_package->type == TY_CYGWIN)
108     return backslash (concat (root_dir, "/bin/", XEMACS_CYGWIN_ARCH_NAME, 0));
109   else
110     return backslash (concat (root_dir, "\\XEmacs-",
111                               xemacs_package->info[xemacs_package->trust].version, 
112                               "\\", XEMACS_NATIVE_ARCH_NAME, 0));
113 }
114
115 char* 
116 find_xemacs_exe_name ()
117 {
118   /* Hack to support older versions. */
119   if (strncmp (xemacs_package->info[xemacs_package->trust].version,
120                "21.1", 4) == 0)
121     return strdup ("runemacs.exe");
122   else if (xemacs_package->type == TY_CYGWIN)
123     return backslash (concat ("xemacs-",
124                               xemacs_package->info[xemacs_package->trust].version, 
125                               ".exe", 0));
126   else
127     return strdup ("xemacs.exe");
128 }
129
130 static void
131 remove_link (char *linkpath, char* title)
132 {
133   if (title)
134     {
135       char *fname = backslash (concat (linkpath, "/", title, ".lnk", 0));
136       msg ("remove_link %s, %s\n", fname, title);
137       if (_access (fname, 0) != 0)
138         return; /* doesn't exist */
139       _unlink (fname);
140     }
141   else 
142     {
143       msg ("remove_link %s\n", linkpath);
144       if (_access (linkpath, 0) != 0)
145         return; /* doesn't exist */
146       _rmdir (linkpath);
147     }
148 }
149
150 static void
151 start_menu (char *title, char *target, int rem, char* args)
152 {
153   char path[_MAX_PATH];
154   LPITEMIDLIST id;
155   int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
156   SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS, &id);
157   SHGetPathFromIDList (id, path);
158 // following lines added because it appears Win95 does not use common programs
159 // unless it comes into play when multiple users for Win95 is enabled
160   msg("Program directory for program link: %s",path);
161   if ( strlen(path) == 0) {
162      SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
163      SHGetPathFromIDList (id, path);
164      msg("Program directory for program link changed to: %s",path);
165   }
166 // end of Win95 addition
167   strcat (path, "\\");
168   strcat (path, XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME);
169   if (rem == 0)
170     make_link (path, title, target, args);
171   else
172     remove_link (path, title);
173 }
174
175 static void
176 desktop_icon (char *title, char *target, int rem)
177 {
178   char path[_MAX_PATH];
179   LPITEMIDLIST id;
180   int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
181   //SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_DESKTOP : CSIDL_COMMON_DESKTOPDIRECTORY, &id);
182   SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_DESKTOPDIRECTORY : CSIDL_DESKTOPDIRECTORY, &id);
183   SHGetPathFromIDList (id, path);
184 // following lines added because it appears Win95 does not use common programs
185 // unless it comes into play when multiple users for Win95 is enabled
186   msg("Desktop directory for desktop link: %s",path);
187   if ( strlen(path) == 0) {
188      SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
189      SHGetPathFromIDList (id, path);
190      msg("Desktop directory for deskop link changed to: %s",path);
191   }
192 // end of Win95 addition
193   if (rem == 0)
194     make_link (path, title, target, "");
195   else
196     remove_link (path, title);
197 }
198
199 static void
200 save_icon ()
201 {
202   iconname = backslash (concat (root_dir, XEMACS_RESOURCE_DIR, 
203                                 "xemacs.ico", 0));
204
205   HRSRC rsrc = FindResource (NULL, "XEMACS.ICON", "FILE");
206   if (rsrc == NULL)
207     {
208       fatal ("FindResource failed");
209     }
210   HGLOBAL res = LoadResource (NULL, rsrc);
211   char *data = (char *) LockResource (res);
212   int len = SizeofResource (NULL, rsrc);
213
214   FILE *f = fopen (iconname, "wb");
215   if (f)
216     {
217       fwrite (data, 1, len, f);
218       fclose (f);
219     }
220 }
221
222 void
223 remove_desktop_setup()
224 {
225   start_menu ("XEmacs", 0, 1, 0);
226   start_menu ("Uninstall XEmacs", 0, 1, 0);
227   start_menu (0, 0, 1, 0);
228   desktop_icon ("XEmacs", 0, 1);
229
230   if (xemacs_package != 0)
231     {
232 #define FROB(exe)         remove_app_path (exe)
233       FROB (find_xemacs_exe_name ());
234       FROB ("runemacs.exe");
235       FROB ("xemacs.exe");
236 #undef FROB
237     }
238 }
239
240 static void
241 do_desktop_setup()
242 {
243   save_icon ();
244
245   if (root_menu && batname) {
246     start_menu ("XEmacs", batname, 0, "");
247     start_menu ("Uninstall XEmacs", uninstname, 0, "-u");
248   }
249
250   if (root_desktop && batname) {
251     desktop_icon ("XEmacs", batname, 0);
252   }
253
254   // set regkeys for the application
255   if (xemacs_package != 0)
256     {
257       int issystem = (root_scope == IDC_ROOT_SYSTEM ? 1 : 0);
258       if (xemacs_package->type == TY_NATIVE
259           || xemacs_package->type == TY_CYGWIN)
260         {
261           if (xemacs_package->type == TY_NATIVE)
262             {
263 #define FROB(exe)         set_app_path ((exe), \
264                         find_xemacs_exe_path (), \
265                         issystem)
266               FROB (find_xemacs_exe_name ());
267               FROB ("runemacs.exe");
268               FROB ("xemacs.exe");
269 #undef FROB
270             }
271           else if (xemacs_package->type == TY_CYGWIN)
272             {
273               int junk;
274               char* root = find_cygwin_root (&junk);
275 #define FROB(exe)       set_app_path ((exe), \
276                         concat (find_xemacs_exe_path (), ";", \
277                                 root, "\\bin;", \
278                                 root, "\\usr\\bin", 0), \
279                         issystem)
280               FROB (find_xemacs_exe_name ());
281               FROB ("runemacs.exe");
282               FROB ("xemacs.exe");
283 #undef FROB
284             }
285           set_install_path (find_xemacs_exe_path(), issystem);
286         }
287       // Register file types
288       if (batname)
289         {
290           if (reg_java)
291             {
292               log (0, "Registering .java files");
293               setup_explorer ("java", "Java Source file", batname);
294               setup_explorer ("jav", "Java Source file", batname);
295             }
296           if (reg_cpp)
297             {
298               log (0, "Registering .cpp files");
299               setup_explorer ("cpp", "C++ Source file", batname);
300               setup_explorer ("cc", "C++ Source file", batname);
301               setup_explorer ("hh", "C++ Header file", batname);
302             }
303           if (reg_c)
304             {
305               log (0, "Registering .c files");
306               setup_explorer ("c", "C Source file", batname);
307               setup_explorer ("h", "C Header file", batname);
308             }
309           if (reg_elisp)
310             {
311               log (0, "Registering .el files");
312               setup_explorer ("el", "E-Lisp Source file", batname);
313             }
314           if (reg_txt)
315             {
316               log (0, "Registering .txt files");
317               setup_explorer ("txt", "Text file", batname);
318             }
319           if (reg_idl)
320             {
321               log (0, "Registering .idl files");
322               setup_explorer ("idl", "OMG IDL file", batname);
323             }
324         }
325     }
326 }
327
328 static int da[] = { IDC_ROOT_DESKTOP, 0 };
329 static int ma[] = { IDC_ROOT_MENU, 0 };
330
331 static int ct[] = { IDC_C_TYPE, 0 };
332 static int javat[] = { IDC_JAVA_TYPE, 0 };
333 static int cppt[] = { IDC_CPP_TYPE, 0 };
334 static int elispt[] = { IDC_ELISP_TYPE, 0 };
335 static int txtt[] = { IDC_TXT_TYPE, 0 };
336 static int idlt[] = { IDC_IDL_TYPE, 0 };
337
338 static void
339 check_if_enable_next (HWND h)
340 {
341   EnableWindow (GetDlgItem (h, IDOK), 1);
342 }
343
344 static void
345 load_dialog (HWND h)
346 {
347   rbset (h, da, root_desktop);
348   rbset (h, ma, root_menu);
349   rbset (h, ct, reg_c);
350   rbset (h, javat, reg_java);
351   rbset (h, cppt, reg_cpp);
352   rbset (h, elispt, reg_elisp);
353   rbset (h, txtt, reg_txt);
354   rbset (h, idlt, reg_idl);
355   check_if_enable_next (h);
356 }
357
358 static int check_desktop (char *title, char *target)
359 {
360   char path[_MAX_PATH];
361   LPITEMIDLIST id;
362   int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
363   SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_DESKTOPDIRECTORY : CSIDL_DESKTOPDIRECTORY, &id);
364   SHGetPathFromIDList (id, path);
365   // following lines added because it appears Win95 does not use common programs
366   // unless it comes into play when multiple users for Win95 is enabled
367   msg ("Desktop directory for desktop link: %s",path);
368   if (strlen (path) == 0) {
369      SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
370      SHGetPathFromIDList (id, path);
371      msg ("Desktop directory for deskop link changed to: %s",path);
372   }
373   // end of Win95 addition
374   char *fname = concat (path, "/", title, ".lnk", 0);
375
376   if (_access (fname, 0) == 0)
377     return 0; /* already exists */
378   
379   fname = concat (path, "/", title, ".pif", 0); /* check for a pif as well */
380   
381   if (_access (fname, 0) == 0)
382     return 0; /* already exists */
383
384   return IDC_ROOT_DESKTOP;
385 }
386
387 static int check_startmenu (char *title, char *target)
388 {
389   char path[_MAX_PATH];
390   LPITEMIDLIST id;
391   int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
392   SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS, &id);
393   SHGetPathFromIDList (id, path);
394   // following lines added because it appears Win95 does not use common programs
395   // unless it comes into play when multiple users for Win95 is enabled
396   msg ("Program directory for program link: %s",path);
397   if (strlen (path) == 0) {
398      SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
399      SHGetPathFromIDList (id, path);
400      msg ("Program directory for program link changed to: %s",path);
401   }
402   // end of Win95 addition
403   strcat (path, "\\");
404   strcat (path, XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME);
405   char *fname = concat (path, "\\", title, ".lnk", 0);
406
407   if (_access (fname, 0) == 0)
408     return 0; /* already exists */
409   
410   fname = concat (path, "\\", title, ".pif", 0); /* check for a pif as well */
411   
412   if (_access (fname, 0) == 0)
413     return 0; /* already exists */
414   
415   return IDC_ROOT_MENU;
416 }
417
418 static void
419 save_dialog (HWND h)
420 {
421   root_desktop= rbget (h, da);
422   root_menu = rbget (h, ma);
423   reg_c = rbget (h, ct);
424   reg_java = rbget (h, javat);
425   reg_cpp = rbget (h, cppt);
426   reg_elisp = rbget (h, elispt);
427   reg_txt = rbget (h, txtt);
428   reg_idl = rbget (h, idlt);
429 }
430
431 static BOOL
432 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
433 {
434   switch (id)
435     {
436
437     case IDC_ROOT_DESKTOP:
438     case IDC_ROOT_MENU:
439       save_dialog (h);
440       check_if_enable_next (h);
441       break;
442
443     case IDOK:
444       save_dialog (h);
445       do_desktop_setup();
446       NEXT (IDD_S_POSTINSTALL);
447       break;
448
449     case IDC_BACK:
450       save_dialog (h);
451       NEXT (IDD_CHOOSE);
452       break;
453
454     case IDCANCEL:
455       NEXT (0);
456       break;
457     }
458   return FALSE;
459 }
460
461 static BOOL CALLBACK
462 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
463 {
464   switch (message)
465     {
466     case WM_INITDIALOG:
467       load_dialog (h);
468       return FALSE;
469     case WM_COMMAND:
470       return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
471     }
472   return FALSE;
473 }
474
475 void
476 do_desktop (HINSTANCE h)
477 {
478   CoInitialize (NULL);
479
480   verinfo.dwOSVersionInfoSize = sizeof (verinfo);
481   GetVersionEx (&verinfo);
482   batname = 0;
483   uninstname = 0;
484
485   if (xemacs_package != 0 && xemacs_package->type != TY_GENERIC)
486     {
487       batname = concat (find_xemacs_exe_path (), "\\",
488                         find_xemacs_exe_name (), 
489                         0);
490       uninstname = concat (find_xemacs_exe_path (), "\\", "setup.exe", 0);
491       root_desktop = check_desktop ("XEmacs", batname);
492       root_menu = check_startmenu ("XEmacs", batname);
493       reg_c = IDC_C_TYPE;
494       reg_cpp = IDC_CPP_TYPE;
495       reg_java = IDC_JAVA_TYPE;
496       reg_elisp = IDC_ELISP_TYPE;
497       reg_txt = IDC_TXT_TYPE;
498       reg_idl = IDC_IDL_TYPE;
499     }
500   else
501     {
502       root_desktop = 0;
503       root_menu = 0;
504       reg_c = 0;
505       reg_cpp = 0;
506       reg_java = 0;
507       reg_elisp = 0;
508       reg_txt = 0;
509       reg_idl = 0;
510     }
511   
512   int rv = 0;
513
514   rv = DialogBox (h, MAKEINTRESOURCE (IDD_DESKTOP), 0, dialog_proc);
515   if (rv == -1)
516     fatal (IDS_DIALOG_FAILED);
517 }