1/* Add entries to the GNU Emacs Program Manager folder.
2   Copyright (C) 1995, 2001, 2002, 2003, 2004, 2005,
3      2006, 2007  Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING.  If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.  */
21
22/****************************************************************************
23 *
24 * Program: addpm	(adds emacs to the Windows program manager)
25 *
26 * Usage:
27 *   	argv[1] = install path for emacs
28 *	argv[2] = full path to icon for emacs (optional)
29 */
30
31#include <windows.h>
32#include <ddeml.h>
33#include <stdlib.h>
34#include <stdio.h>
35
36HDDEDATA CALLBACK
37DdeCallback (UINT uType, UINT uFmt, HCONV hconv,
38	     HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
39	     DWORD dwData1, DWORD dwData2)
40{
41  return ((HDDEDATA) NULL);
42}
43
44#define DdeCommand(str) 	\
45	DdeClientTransaction (str, strlen (str)+1, HConversation, (HSZ)NULL, \
46		              CF_TEXT, XTYP_EXECUTE, 30000, NULL)
47
48#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
49
50static struct entry
51{
52  char *name;
53  char *value;
54}
55env_vars[] =
56{
57  {"emacs_dir", NULL},
58  {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
59  {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
60  {"EMACSDATA", "%emacs_dir%/etc"},
61  {"EMACSPATH", "%emacs_dir%/bin"},
62  /* We no longer set INFOPATH because Info-default-directory-list
63     is then ignored.  */
64  /*  {"INFOPATH", "%emacs_dir%/info"},  */
65  {"EMACSDOC", "%emacs_dir%/etc"},
66  {"TERM", "cmd"}
67};
68
69BOOL
70add_registry (path)
71     char *path;
72{
73  HKEY hrootkey = NULL;
74  int i;
75  BOOL ok = TRUE;
76
77  /* Previous versions relied on registry settings, but we do not need
78     them any more.  If registry settings are installed from a previous
79     version, replace them to ensure they are the current settings.
80     Otherwise, do nothing.  */
81
82  /* Check both the current user and the local machine to see if we
83     have any resources.  */
84
85  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT,
86		      REG_OPTION_NON_VOLATILE,
87		      KEY_WRITE, &hrootkey) != ERROR_SUCCESS
88      && RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT,
89			 REG_OPTION_NON_VOLATILE,
90			 KEY_WRITE, &hrootkey) != ERROR_SUCCESS)
91    {
92      return FALSE;
93    }
94
95  for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
96    {
97      char * value = env_vars[i].value ? env_vars[i].value : path;
98
99      if (RegSetValueEx (hrootkey, env_vars[i].name,
100			 0, REG_EXPAND_SZ,
101			 value, lstrlen (value) + 1) != ERROR_SUCCESS)
102	ok = FALSE;
103    }
104
105  RegCloseKey (hrootkey);
106
107  return (ok);
108}
109
110int
111main (argc, argv)
112     int argc;
113     char *argv[];
114{
115  DWORD idDde = 0;
116  HCONV HConversation;
117  HSZ ProgMan;
118  char modname[MAX_PATH];
119  char additem[MAX_PATH*2 + 100];
120  char *prog_name;
121  char *emacs_path;
122  char *p;
123  int quiet = 0;
124
125  /* If no args specified, use our location to set emacs_path.  */
126#if 0
127  if (argc < 2 || argc > 3)
128    {
129      fprintf (stderr, "usage: addpm [-q] [emacs_path [icon_path]]\n");
130      exit (1);
131    }
132#endif
133
134  if (argc > 1
135      && (argv[1][0] == '/' || argv[1][0] == '-')
136      && argv[1][1] == 'q')
137    {
138      quiet = 1;
139      --argc;
140      ++argv;
141    }
142
143  if (argc > 1)
144    emacs_path = argv[1];
145  else
146    {
147      if (!GetModuleFileName (NULL, modname, MAX_PATH) ||
148	  (p = strrchr (modname, '\\')) == NULL)
149	{
150	  fprintf (stderr, "fatal error");
151	  exit (1);
152	}
153      *p = 0;
154
155      /* Set emacs_path to emacs_dir if we are in "%emacs_dir%\bin".  */
156      if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
157	{
158	  *p = 0;
159	  emacs_path = modname;
160	}
161      else
162	{
163	  fprintf (stderr, "usage: addpm emacs_path [icon_path]\n");
164	  exit (1);
165	}
166
167      /* Tell user what we are going to do.  */
168      if (!quiet)
169	{
170	  int result;
171
172	  char msg[ MAX_PATH ];
173	  sprintf (msg, "Install Emacs at %s?\n", emacs_path);
174	  result = MessageBox (NULL, msg, "Install Emacs",
175			       MB_OKCANCEL | MB_ICONQUESTION);
176	  if (result != IDOK)
177	    {
178	      fprintf (stderr, "Install cancelled\n");
179	      exit (1);
180	    }
181	}
182    }
183
184  add_registry (emacs_path);
185  prog_name =  "runemacs.exe";
186
187  DdeInitialize (&idDde, (PFNCALLBACK)DdeCallback, APPCMD_CLIENTONLY, 0);
188
189  ProgMan = DdeCreateStringHandle (idDde, "PROGMAN", CP_WINANSI);
190
191  HConversation = DdeConnect (idDde, ProgMan, ProgMan, NULL);
192  if (HConversation != 0)
193    {
194      DdeCommand ("[CreateGroup (\"Gnu Emacs\")]");
195      DdeCommand ("[ReplaceItem (Emacs)]");
196      if (argc > 2)
197	sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs, \"%s\")]",
198		 emacs_path, prog_name, argv[2]);
199      else
200	sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs)]",
201		 emacs_path, prog_name);
202      DdeCommand (additem);
203
204      DdeDisconnect (HConversation);
205    }
206
207  DdeFreeStringHandle (idDde, ProgMan);
208
209  DdeUninitialize (idDde);
210
211  return (0);
212}
213
214/* arch-tag: f923609d-b781-4ef4-abce-ca0da29cbbf0
215   (do not change this comment) */
216