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