root/trunk/nt/addpm.c

Revision 4220, 7.8 kB (checked in by miyoshi, 5 months ago)

Sync up with Emacs22.2.

  • Property svn:eol-style set to native
Line 
1 /* Add entries to the GNU Emacs Program Manager folder.
2    Copyright (C) 1995, 2001, 2002, 2003, 2004, 2005,
3       2006, 2007, 2008  Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, 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 #include <malloc.h>
36
37 HDDEDATA CALLBACK
38 DdeCallback (UINT uType, UINT uFmt, HCONV hconv,
39              HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
40              DWORD dwData1, DWORD dwData2)
41 {
42   return ((HDDEDATA) NULL);
43 }
44
45 #define DdeCommand(str)         \
46         DdeClientTransaction (str, strlen (str)+1, HConversation, (HSZ)NULL, \
47                               CF_TEXT, XTYP_EXECUTE, 30000, NULL)
48
49 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
50 #define REG_GTK "SOFTWARE\\GTK\\2.0"
51 #define REG_APP_PATH \
52   "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\emacs.exe"
53
54 static struct entry
55 {
56   char *name;
57   char *value;
58 }
59 env_vars[] =
60 {
61   {"emacs_dir", NULL},
62   {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
63   {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
64   {"EMACSDATA", "%emacs_dir%/etc"},
65   {"EMACSPATH", "%emacs_dir%/bin"},
66   /* We no longer set INFOPATH because Info-default-directory-list
67      is then ignored.  */
68   /*  {"INFOPATH", "%emacs_dir%/info"},  */
69   {"EMACSDOC", "%emacs_dir%/etc"},
70   {"TERM", "cmd"}
71 };
72
73 BOOL
74 add_registry (path)
75      char *path;
76 {
77   HKEY hrootkey = NULL;
78   int i;
79   BOOL ok = TRUE;
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   */
91   if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, REG_APP_PATH, 0, "",
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.  */
100       emacs_path = (char *) alloca (len);
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     }
131
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
137   /* Check both the current user and the local machine to see if we
138      have any resources.  */
139
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)
146     {
147       return FALSE;
148     }
149
150   for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
151     {
152       char * value = env_vars[i].value ? env_vars[i].value : path;
153
154       if (RegSetValueEx (hrootkey, env_vars[i].name,
155                          0, REG_EXPAND_SZ,
156                          value, lstrlen (value) + 1) != ERROR_SUCCESS)
157         ok = FALSE;
158     }
159
160   RegCloseKey (hrootkey);
161
162   return (ok);
163 }
164
165 int
166 main (argc, argv)
167      int argc;
168      char *argv[];
169 {
170   DWORD idDde = 0;
171   HCONV HConversation;
172   HSZ ProgMan;
173   char modname[MAX_PATH];
174   char additem[MAX_PATH*2 + 100];
175   char *prog_name;
176   char *emacs_path;
177   char *p;
178   int quiet = 0;
179
180   /* If no args specified, use our location to set emacs_path.  */
181 #if 0
182   if (argc < 2 || argc > 3)
183     {
184       fprintf (stderr, "usage: addpm [-q] [emacs_path [icon_path]]\n");
185       exit (1);
186     }
187 #endif
188
189   if (argc > 1
190       && (argv[1][0] == '/' || argv[1][0] == '-')
191       && argv[1][1] == 'q')
192     {
193       quiet = 1;
194       --argc;
195       ++argv;
196     }
197
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.  */
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         }
237     }
238
239   add_registry (emacs_path);
240   prog_name =  "runemacs.exe";
241
242   DdeInitialize (&idDde, (PFNCALLBACK)DdeCallback, APPCMD_CLIENTONLY, 0);
243
244   ProgMan = DdeCreateStringHandle (idDde, "PROGMAN", CP_WINANSI);
245
246   HConversation = DdeConnect (idDde, ProgMan, ProgMan, NULL);
247   if (HConversation != 0)
248     {
249       DdeCommand ("[CreateGroup (\"Gnu Emacs\")]");
250       DdeCommand ("[ReplaceItem (Emacs)]");
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);
257       DdeCommand (additem);
258
259       DdeDisconnect (HConversation);
260     }
261
262   DdeFreeStringHandle (idDde, ProgMan);
263
264   DdeUninitialize (idDde);
265
266   return (0);
267 }
268
269 /* arch-tag: f923609d-b781-4ef4-abce-ca0da29cbbf0
270    (do not change this comment) */
Note: See TracBrowser for help on using the browser.