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