Merge from emacs--rel--22
[bpt/emacs.git] / nt / addpm.c
CommitLineData
cef9e134 1/* Add entries to the GNU Emacs Program Manager folder.
eef0be9e
GM
2 Copyright (C) 1995, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3 2008 Free Software Foundation, Inc.
cef9e134 4
bf2b146b
EN
5This file is part of GNU Emacs.
6
eef0be9e 7GNU Emacs is free software: you can redistribute it and/or modify
bf2b146b 8it under the terms of the GNU General Public License as published by
eef0be9e
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
bf2b146b
EN
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
eef0be9e 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
cef9e134 19
cef9e134 20/****************************************************************************
6fbcbee7
RS
21 *
22 * Program: addpm (adds emacs to the Windows program manager)
23 *
24 * Usage:
2cc1905e 25 * argv[1] = install path for emacs
6fbcbee7
RS
26 * argv[2] = full path to icon for emacs (optional)
27 */
cef9e134 28
6fbcbee7
RS
29#include <windows.h>
30#include <ddeml.h>
31#include <stdlib.h>
32#include <stdio.h>
c44b4b46 33#include <malloc.h>
cef9e134 34
177c0ea7 35HDDEDATA CALLBACK
2cc1905e
GV
36DdeCallback (UINT uType, UINT uFmt, HCONV hconv,
37 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
38 DWORD dwData1, DWORD dwData2)
6fbcbee7 39{
2cc1905e 40 return ((HDDEDATA) NULL);
6fbcbee7 41}
cef9e134 42
6fbcbee7 43#define DdeCommand(str) \
2cc1905e 44 DdeClientTransaction (str, strlen (str)+1, HConversation, (HSZ)NULL, \
6fbcbee7 45 CF_TEXT, XTYP_EXECUTE, 30000, NULL)
cef9e134 46
c6e63684 47#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
f1cefe09
JR
48#define REG_GTK "SOFTWARE\\GTK\\2.0"
49#define REG_APP_PATH \
50 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\emacs.exe"
2cc1905e
GV
51
52static struct entry
53{
54 char *name;
55 char *value;
177c0ea7
JB
56}
57env_vars[] =
2cc1905e 58{
c6e63684 59 {"emacs_dir", NULL},
5488afcc 60 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
0655d4d4 61 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
26b430b7
RS
62 {"EMACSDATA", "%emacs_dir%/etc"},
63 {"EMACSPATH", "%emacs_dir%/bin"},
9296c0e8
GV
64 /* We no longer set INFOPATH because Info-default-directory-list
65 is then ignored. */
66 /* {"INFOPATH", "%emacs_dir%/info"}, */
26b430b7 67 {"EMACSDOC", "%emacs_dir%/etc"},
2cc1905e
GV
68 {"TERM", "cmd"}
69};
70
177c0ea7 71BOOL
2cc1905e
GV
72add_registry (path)
73 char *path;
74{
75 HKEY hrootkey = NULL;
2cc1905e
GV
76 int i;
77 BOOL ok = TRUE;
f1cefe09
JR
78 DWORD size;
79
80 /* Record the location of Emacs to the App Paths key if we have
81 sufficient permissions to do so. This helps Windows find emacs quickly
82 if the user types emacs.exe in the "Run Program" dialog without having
83 emacs on their path. Some applications also use the same registry key
84 to discover the installation directory for programs they are looking for.
85 Multiple installations cannot be handled by this method, but it does not
86 affect the general operation of other installations of Emacs, and we
87 are blindly overwriting the Start Menu entries already.
88 */
c44b4b46 89 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, REG_APP_PATH, 0, "",
f1cefe09
JR
90 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
91 &hrootkey, NULL) == ERROR_SUCCESS)
92 {
93 int len;
94 char *emacs_path;
95 HKEY gtk_key = NULL;
96
97 len = strlen (path) + 15; /* \bin\emacs.exe + terminator. */
c44b4b46 98 emacs_path = (char *) alloca (len);
f1cefe09
JR
99 sprintf (emacs_path, "%s\\bin\\emacs.exe", path);
100
101 RegSetValueEx (hrootkey, NULL, 0, REG_SZ, emacs_path, len);
102
103 /* Look for a GTK installation. If found, add it to the library search
104 path for Emacs so that the image libraries it provides are available
105 to Emacs regardless of whether it is in the path or not. */
106 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_GTK, REG_OPTION_NON_VOLATILE,
107 KEY_READ, &gtk_key) == ERROR_SUCCESS)
108 {
109 if (RegQueryValueEx (gtk_key, "DllPath", NULL, NULL,
110 NULL, &size) == ERROR_SUCCESS)
111 {
112 char *gtk_path = (char *) alloca (size);
113 if (RegQueryValueEx (gtk_key, "DllPath", NULL, NULL,
114 gtk_path, &size) == ERROR_SUCCESS)
115 {
116 /* Make sure the emacs bin directory continues to be searched
117 first by including it as well. */
118 char *dll_paths;
119 len = strlen (path) + 5 + size;
120 dll_paths = (char *) alloca (size + strlen (path) + 1);
121 sprintf (dll_paths, "%s\\bin;%s", path, gtk_path);
122 RegSetValueEx (hrootkey, "Path", 0, REG_SZ, dll_paths, len);
123 }
124 }
125 RegCloseKey (gtk_key);
126 }
127 RegCloseKey (hrootkey);
128 }
177c0ea7 129
ebe98f49
JR
130 /* Previous versions relied on registry settings, but we do not need
131 them any more. If registry settings are installed from a previous
132 version, replace them to ensure they are the current settings.
133 Otherwise, do nothing. */
134
177c0ea7 135 /* Check both the current user and the local machine to see if we
2cc1905e 136 have any resources. */
177c0ea7 137
ebe98f49
JR
138 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT,
139 REG_OPTION_NON_VOLATILE,
140 KEY_WRITE, &hrootkey) != ERROR_SUCCESS
141 && RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT,
142 REG_OPTION_NON_VOLATILE,
143 KEY_WRITE, &hrootkey) != ERROR_SUCCESS)
2cc1905e
GV
144 {
145 return FALSE;
146 }
177c0ea7
JB
147
148 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
2cc1905e
GV
149 {
150 char * value = env_vars[i].value ? env_vars[i].value : path;
177c0ea7 151
2cc1905e
GV
152 if (RegSetValueEx (hrootkey, env_vars[i].name,
153 0, REG_EXPAND_SZ,
154 value, lstrlen (value) + 1) != ERROR_SUCCESS)
155 ok = FALSE;
177c0ea7
JB
156 }
157
2cc1905e 158 RegCloseKey (hrootkey);
177c0ea7 159
2cc1905e
GV
160 return (ok);
161}
162
163int
6fbcbee7
RS
164main (argc, argv)
165 int argc;
177c0ea7 166 char *argv[];
cef9e134 167{
65cd6687 168 DWORD idDde = 0;
6fbcbee7
RS
169 HCONV HConversation;
170 HSZ ProgMan;
65cd6687 171 char modname[MAX_PATH];
cef9e134 172 char additem[MAX_PATH*2 + 100];
9296c0e8 173 char *prog_name;
65cd6687
GV
174 char *emacs_path;
175 char *p;
5205d900 176 int quiet = 0;
cef9e134 177
65cd6687
GV
178 /* If no args specified, use our location to set emacs_path. */
179#if 0
6fbcbee7 180 if (argc < 2 || argc > 3)
cef9e134 181 {
f4c6fac4 182 fprintf (stderr, "usage: addpm [-q] [emacs_path [icon_path]]\n");
2cc1905e 183 exit (1);
cef9e134 184 }
65cd6687 185#endif
cef9e134 186
f4c6fac4
JR
187 if (argc > 1
188 && (argv[1][0] == '/' || argv[1][0] == '-')
189 && argv[1][1] == 'q')
5205d900
AI
190 {
191 quiet = 1;
192 --argc;
193 ++argv;
194 }
195
65cd6687
GV
196 if (argc > 1)
197 emacs_path = argv[1];
198 else
199 {
200 if (!GetModuleFileName (NULL, modname, MAX_PATH) ||
201 (p = strrchr (modname, '\\')) == NULL)
202 {
203 fprintf (stderr, "fatal error");
204 exit (1);
205 }
206 *p = 0;
207
208 /* Set emacs_path to emacs_dir if we are in "%emacs_dir%\bin". */
209 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
210 {
211 *p = 0;
212 emacs_path = modname;
213 }
214 else
215 {
216 fprintf (stderr, "usage: addpm emacs_path [icon_path]\n");
217 exit (1);
218 }
219
220 /* Tell user what we are going to do. */
5205d900
AI
221 if (!quiet)
222 {
223 int result;
224
225 char msg[ MAX_PATH ];
226 sprintf (msg, "Install Emacs at %s?\n", emacs_path);
227 result = MessageBox (NULL, msg, "Install Emacs",
228 MB_OKCANCEL | MB_ICONQUESTION);
229 if (result != IDOK)
230 {
231 fprintf (stderr, "Install cancelled\n");
232 exit (1);
233 }
234 }
65cd6687
GV
235 }
236
5205d900
AI
237 add_registry (emacs_path);
238 prog_name = "runemacs.exe";
2cc1905e 239
6fbcbee7 240 DdeInitialize (&idDde, (PFNCALLBACK)DdeCallback, APPCMD_CLIENTONLY, 0);
cef9e134 241
6fbcbee7 242 ProgMan = DdeCreateStringHandle (idDde, "PROGMAN", CP_WINANSI);
cef9e134 243
9296c0e8
GV
244 HConversation = DdeConnect (idDde, ProgMan, ProgMan, NULL);
245 if (HConversation != 0)
cef9e134 246 {
9296c0e8 247 DdeCommand ("[CreateGroup (\"Gnu Emacs\")]");
2cc1905e 248 DdeCommand ("[ReplaceItem (Emacs)]");
9296c0e8
GV
249 if (argc > 2)
250 sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs, \"%s\")]",
251 emacs_path, prog_name, argv[2]);
252 else
253 sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs)]",
254 emacs_path, prog_name);
6fbcbee7
RS
255 DdeCommand (additem);
256
257 DdeDisconnect (HConversation);
cef9e134
GV
258 }
259
6fbcbee7
RS
260 DdeFreeStringHandle (idDde, ProgMan);
261
262 DdeUninitialize (idDde);
cef9e134 263
6fbcbee7 264 return (0);
cef9e134 265}
ab5796a9
MB
266
267/* arch-tag: f923609d-b781-4ef4-abce-ca0da29cbbf0
268 (do not change this comment) */