blob: 5a4caac4255b5af7924363d5440557ae651854d3 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * dosinst.c: Install program for Vim on MS-DOS and MS-Windows
12 *
13 * Compile with Make_mvc.mak, Make_bc3.mak, Make_bc5.mak or Make_djg.mak.
14 */
15
16/*
17 * Include common code for dosinst.c and uninstal.c.
18 */
19#define DOSINST
20#include "dosinst.h"
21
Bram Moolenaar6199d432017-10-14 19:05:44 +020022#define GVIMEXT64_PATH "GvimExt64\\gvimext.dll"
23#define GVIMEXT32_PATH "GvimExt32\\gvimext.dll"
24
Bram Moolenaar071d4272004-06-13 20:20:40 +000025/* Macro to do an error check I was typing over and over */
26#define CHECK_REG_ERROR(code) if (code != ERROR_SUCCESS) { printf("%ld error number: %ld\n", (long)__LINE__, (long)code); return 1; }
27
28int has_vim = 0; /* installable vim.exe exists */
29int has_gvim = 0; /* installable gvim.exe exists */
30
31char oldvimrc[BUFSIZE]; /* name of existing vimrc file */
32char vimrc[BUFSIZE]; /* name of vimrc file to create */
33
34char *default_bat_dir = NULL; /* when not NULL, use this as the default
35 directory to write .bat files in */
36char *default_vim_dir = NULL; /* when not NULL, use this as the default
37 install dir for NSIS */
Bram Moolenaar071d4272004-06-13 20:20:40 +000038
39/*
40 * Structure used for each choice the user can make.
41 */
42struct choice
43{
44 int active; /* non-zero when choice is active */
45 char *text; /* text displayed for this choice */
46 void (*changefunc)(int idx); /* function to change this choice */
47 int arg; /* argument for function */
48 void (*installfunc)(int idx); /* function to install this choice */
49};
50
51struct choice choices[30]; /* choices the user can make */
52int choice_count = 0; /* number of choices available */
53
54#define TABLE_SIZE(s) (int)(sizeof(s) / sizeof(*s))
55
56enum
57{
58 compat_vi = 1,
59 compat_some_enhancements,
60 compat_all_enhancements
61};
62char *(compat_choices[]) =
63{
64 "\nChoose the default way to run Vim:",
65 "Vi compatible",
Bram Moolenaarfff2bee2010-05-15 13:56:02 +020066 "with some Vim enhancements",
Bram Moolenaar071d4272004-06-13 20:20:40 +000067 "with syntax highlighting and other features switched on",
68};
69int compat_choice = (int)compat_all_enhancements;
70char *compat_text = "- run Vim %s";
71
72enum
73{
74 remap_no = 1,
75 remap_win
76};
77char *(remap_choices[]) =
78{
79 "\nChoose:",
80 "Do not remap keys for Windows behavior",
Bram Moolenaar6199d432017-10-14 19:05:44 +020081 "Remap a few keys for Windows behavior (CTRL-V, CTRL-C, CTRL-F, etc)",
Bram Moolenaar071d4272004-06-13 20:20:40 +000082};
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +020083int remap_choice = (int)remap_no;
Bram Moolenaar071d4272004-06-13 20:20:40 +000084char *remap_text = "- %s";
85
86enum
87{
88 mouse_xterm = 1,
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +020089 mouse_mswin,,
90 mouse_default
Bram Moolenaar071d4272004-06-13 20:20:40 +000091};
92char *(mouse_choices[]) =
93{
94 "\nChoose the way how Vim uses the mouse:",
95 "right button extends selection (the Unix way)",
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +020096 "right button has a popup menu, left button starts select mode (the Windows way)",
97 "right button has a popup menu, left button starts visual mode",
Bram Moolenaar071d4272004-06-13 20:20:40 +000098};
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +020099int mouse_choice = (int)mouse_default;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100char *mouse_text = "- The mouse %s";
101
102enum
103{
104 vimfiles_dir_none = 1,
105 vimfiles_dir_vim,
106 vimfiles_dir_home
107};
108static char *(vimfiles_dir_choices[]) =
109{
110 "\nCreate plugin directories:",
111 "No",
112 "In the VIM directory",
113 "In your HOME directory",
114};
115static int vimfiles_dir_choice;
116
117/* non-zero when selected to install the popup menu entry. */
118static int install_popup = 0;
119
120/* non-zero when selected to install the "Open with" entry. */
121static int install_openwith = 0;
122
123/* non-zero when need to add an uninstall entry in the registry */
124static int need_uninstall_entry = 0;
125
126/*
127 * Definitions of the directory name (under $VIM) of the vimfiles directory
128 * and its subdirectories:
129 */
130static char *(vimfiles_subdirs[]) =
131{
132 "colors",
133 "compiler",
134 "doc",
135 "ftdetect",
136 "ftplugin",
137 "indent",
138 "keymap",
139 "plugin",
140 "syntax",
141};
142
143/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144 * Obtain a choice from a table.
145 * First entry is a question, others are choices.
146 */
147 static int
148get_choice(char **table, int entries)
149{
150 int answer;
151 int idx;
152 char dummy[100];
153
154 do
155 {
156 for (idx = 0; idx < entries; ++idx)
157 {
158 if (idx)
159 printf("%2d ", idx);
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +0200160 puts(table[idx]);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000161 }
162 printf("Choice: ");
163 if (scanf("%d", &answer) != 1)
164 {
165 scanf("%99s", dummy);
166 answer = 0;
167 }
168 }
169 while (answer < 1 || answer >= entries);
170
171 return answer;
172}
173
174/*
175 * Check if the user unpacked the archives properly.
176 * Sets "runtimeidx".
177 */
178 static void
179check_unpack(void)
180{
181 char buf[BUFSIZE];
182 FILE *fd;
183 struct stat st;
184
185 /* check for presence of the correct version number in installdir[] */
186 runtimeidx = strlen(installdir) - strlen(VIM_VERSION_NODOT);
187 if (runtimeidx <= 0
188 || stricmp(installdir + runtimeidx, VIM_VERSION_NODOT) != 0
189 || (installdir[runtimeidx - 1] != '/'
190 && installdir[runtimeidx - 1] != '\\'))
191 {
192 printf("ERROR: Install program not in directory \"%s\"\n",
193 VIM_VERSION_NODOT);
194 printf("This program can only work when it is located in its original directory\n");
195 myexit(1);
196 }
197
198 /* check if filetype.vim is present, which means the runtime archive has
199 * been unpacked */
200 sprintf(buf, "%s\\filetype.vim", installdir);
201 if (stat(buf, &st) < 0)
202 {
203 printf("ERROR: Cannot find filetype.vim in \"%s\"\n", installdir);
204 printf("It looks like you did not unpack the runtime archive.\n");
205 printf("You must unpack the runtime archive \"vim%srt.zip\" before installing.\n",
206 VIM_VERSION_NODOT + 3);
207 myexit(1);
208 }
209
210 /* Check if vim.exe or gvim.exe is in the current directory. */
211 if ((fd = fopen("gvim.exe", "r")) != NULL)
212 {
213 fclose(fd);
214 has_gvim = 1;
215 }
216 if ((fd = fopen("vim.exe", "r")) != NULL)
217 {
218 fclose(fd);
219 has_vim = 1;
220 }
221 if (!has_gvim && !has_vim)
222 {
223 printf("ERROR: Cannot find any Vim executables in \"%s\"\n\n",
224 installdir);
225 myexit(1);
226 }
227}
228
229/*
230 * Compare paths "p[plen]" to "q[qlen]". Return 0 if they match.
231 * Ignores case and differences between '/' and '\'.
232 * "plen" and "qlen" can be negative, strlen() is used then.
233 */
234 static int
235pathcmp(char *p, int plen, char *q, int qlen)
236{
237 int i;
238
239 if (plen < 0)
240 plen = strlen(p);
241 if (qlen < 0)
242 qlen = strlen(q);
243 for (i = 0; ; ++i)
244 {
245 /* End of "p": check if "q" also ends or just has a slash. */
246 if (i == plen)
247 {
248 if (i == qlen) /* match */
249 return 0;
250 if (i == qlen - 1 && (q[i] == '\\' || q[i] == '/'))
251 return 0; /* match with trailing slash */
252 return 1; /* no match */
253 }
254
255 /* End of "q": check if "p" also ends or just has a slash. */
256 if (i == qlen)
257 {
258 if (i == plen) /* match */
259 return 0;
260 if (i == plen - 1 && (p[i] == '\\' || p[i] == '/'))
261 return 0; /* match with trailing slash */
262 return 1; /* no match */
263 }
264
265 if (!(mytoupper(p[i]) == mytoupper(q[i])
266 || ((p[i] == '/' || p[i] == '\\')
267 && (q[i] == '/' || q[i] == '\\'))))
268 return 1; /* no match */
269 }
270 /*NOTREACHED*/
271}
272
273/*
274 * If the executable "**destination" is in the install directory, find another
275 * one in $PATH.
276 * On input "**destination" is the path of an executable in allocated memory
277 * (or NULL).
278 * "*destination" is set to NULL or the location of the file.
279 */
280 static void
281findoldfile(char **destination)
282{
283 char *bp = *destination;
284 size_t indir_l = strlen(installdir);
285 char *cp = bp + indir_l;
286 char *tmpname;
287 char *farname;
288
289 /*
290 * No action needed if exe not found or not in this directory.
291 */
292 if (bp == NULL
293 || strnicmp(bp, installdir, indir_l) != 0
294 || strchr("/\\", *cp++) == NULL
295 || strchr(cp, '\\') != NULL
296 || strchr(cp, '/') != NULL)
297 return;
298
299 tmpname = alloc((int)strlen(cp) + 1);
300 strcpy(tmpname, cp);
301 tmpname[strlen(tmpname) - 1] = 'x'; /* .exe -> .exx */
302
303 if (access(tmpname, 0) == 0)
304 {
305 printf("\nERROR: %s and %s clash. Remove or rename %s.\n",
306 tmpname, cp, tmpname);
307 myexit(1);
308 }
309
310 if (rename(cp, tmpname) != 0)
311 {
312 printf("\nERROR: failed to rename %s to %s: %s\n",
313 cp, tmpname, strerror(0));
314 myexit(1);
315 }
316
317 farname = searchpath_save(cp);
318
319 if (rename(tmpname, cp) != 0)
320 {
321 printf("\nERROR: failed to rename %s back to %s: %s\n",
322 tmpname, cp, strerror(0));
323 myexit(1);
324 }
325
326 free(*destination);
327 free(tmpname);
328 *destination = farname;
329}
330
331/*
332 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
333 * When "check_bat_only" is TRUE, only find "default_bat_dir".
334 */
335 static void
336find_bat_exe(int check_bat_only)
337{
338 int i;
339
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000340 /* avoid looking in the "installdir" by chdir to system root */
341 mch_chdir(sysdrive);
342 mch_chdir("\\");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000343
344 for (i = 1; i < TARGET_COUNT; ++i)
345 {
346 targets[i].oldbat = searchpath_save(targets[i].batname);
347 if (!check_bat_only)
348 targets[i].oldexe = searchpath_save(targets[i].exename);
349
350 if (default_bat_dir == NULL && targets[i].oldbat != NULL)
351 {
352 default_bat_dir = alloc(strlen(targets[i].oldbat) + 1);
353 strcpy(default_bat_dir, targets[i].oldbat);
354 remove_tail(default_bat_dir);
355 }
356 if (check_bat_only && targets[i].oldbat != NULL)
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000357 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358 free(targets[i].oldbat);
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000359 targets[i].oldbat = NULL;
360 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000361 }
362
363 mch_chdir(installdir);
364}
365
Bram Moolenaar071d4272004-06-13 20:20:40 +0000366/*
367 * Get the value of $VIMRUNTIME or $VIM and write it in $TEMP/vimini.ini, so
368 * that NSIS can read it.
369 * When not set, use the directory of a previously installed Vim.
370 */
371 static void
372get_vim_env(void)
373{
374 char *vim;
375 char buf[BUFSIZE];
376 FILE *fd;
377 char fname[BUFSIZE];
378
379 /* First get $VIMRUNTIME. If it's set, remove the tail. */
380 vim = getenv("VIMRUNTIME");
Bram Moolenaar181ace22013-02-13 14:36:44 +0100381 if (vim != NULL && *vim != 0 && strlen(vim) < BUFSIZE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000382 {
383 strcpy(buf, vim);
384 remove_tail(buf);
385 vim = buf;
386 }
387 else
388 {
389 vim = getenv("VIM");
390 if (vim == NULL || *vim == 0)
391 {
392 /* Use the directory from an old uninstall entry. */
393 if (default_vim_dir != NULL)
394 vim = default_vim_dir;
395 else
396 /* Let NSIS know there is no default, it should use
Bram Moolenaarb8017e72007-05-10 18:59:07 +0000397 * $PROGRAMFILES. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000398 vim = "";
399 }
400 }
401
402 /* NSIS also uses GetTempPath(), thus we should get the same directory
403 * name as where NSIS will look for vimini.ini. */
404 GetTempPath(BUFSIZE, fname);
405 add_pathsep(fname);
406 strcat(fname, "vimini.ini");
407
408 fd = fopen(fname, "w");
409 if (fd != NULL)
410 {
411 /* Make it look like an .ini file, so that NSIS can read it with a
412 * ReadINIStr command. */
413 fprintf(fd, "[vimini]\n");
414 fprintf(fd, "dir=\"%s\"\n", vim);
415 fclose(fd);
416 }
417 else
418 {
419 printf("Failed to open %s\n", fname);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200420 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000421 }
422}
423
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200424static int num_windows;
425
426/*
427 * Callback used for EnumWindows():
428 * Count the window if the title looks like it is for the uninstaller.
429 */
430/*ARGSUSED*/
431 static BOOL CALLBACK
432window_cb(HWND hwnd, LPARAM lparam)
433{
434 char title[256];
435
436 title[0] = 0;
437 GetWindowText(hwnd, title, 256);
438 if (strstr(title, "Vim ") != NULL && strstr(title, "Uninstall:") != NULL)
439 ++num_windows;
440 return TRUE;
441}
442
Bram Moolenaar071d4272004-06-13 20:20:40 +0000443/*
444 * Check for already installed Vims.
445 * Return non-zero when found one.
446 */
447 static int
Bram Moolenaar442b4222010-05-24 21:34:22 +0200448uninstall_check(int skip_question)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000449{
450 HKEY key_handle;
451 HKEY uninstall_key_handle;
452 char *uninstall_key = "software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
453 char subkey_name_buff[BUFSIZE];
454 char temp_string_buffer[BUFSIZE];
455 DWORD local_bufsize = BUFSIZE;
456 FILETIME temp_pfiletime;
457 DWORD key_index;
458 char input;
459 long code;
460 DWORD value_type;
461 DWORD orig_num_keys;
462 DWORD new_num_keys;
463 int foundone = 0;
464
Bram Moolenaar760d14a2010-07-31 22:03:44 +0200465 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0,
466 KEY_WOW64_64KEY | KEY_READ, &key_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467 CHECK_REG_ERROR(code);
468
469 for (key_index = 0;
470 RegEnumKeyEx(key_handle, key_index, subkey_name_buff, &local_bufsize,
471 NULL, NULL, NULL, &temp_pfiletime) != ERROR_NO_MORE_ITEMS;
472 key_index++)
473 {
474 local_bufsize = BUFSIZE;
475 if (strncmp("Vim", subkey_name_buff, 3) == 0)
476 {
477 /* Open the key named Vim* */
Bram Moolenaar760d14a2010-07-31 22:03:44 +0200478 code = RegOpenKeyEx(key_handle, subkey_name_buff, 0,
479 KEY_WOW64_64KEY | KEY_READ, &uninstall_key_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000480 CHECK_REG_ERROR(code);
481
482 /* get the DisplayName out of it to show the user */
483 code = RegQueryValueEx(uninstall_key_handle, "displayname", 0,
484 &value_type, (LPBYTE)temp_string_buffer,
485 &local_bufsize);
486 local_bufsize = BUFSIZE;
487 CHECK_REG_ERROR(code);
488
489 foundone = 1;
490 printf("\n*********************************************************\n");
491 printf("Vim Install found what looks like an existing Vim version.\n");
492 printf("The name of the entry is:\n");
493 printf("\n \"%s\"\n\n", temp_string_buffer);
494
495 printf("Installing the new version will disable part of the existing version.\n");
496 printf("(The batch files used in a console and the \"Edit with Vim\" entry in\n");
497 printf("the popup menu will use the new version)\n");
498
Bram Moolenaar442b4222010-05-24 21:34:22 +0200499 if (skip_question)
500 printf("\nRunning uninstall program for \"%s\"\n", temp_string_buffer);
501 else
502 printf("\nDo you want to uninstall \"%s\" now?\n(y)es/(n)o) ", temp_string_buffer);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000503 fflush(stdout);
504
505 /* get the UninstallString */
506 code = RegQueryValueEx(uninstall_key_handle, "uninstallstring", 0,
507 &value_type, (LPBYTE)temp_string_buffer, &local_bufsize);
508 local_bufsize = BUFSIZE;
509 CHECK_REG_ERROR(code);
510
511 /* Remember the directory, it is used as the default for NSIS. */
512 default_vim_dir = alloc(strlen(temp_string_buffer) + 1);
513 strcpy(default_vim_dir, temp_string_buffer);
514 remove_tail(default_vim_dir);
515 remove_tail(default_vim_dir);
516
517 input = 'n';
518 do
519 {
520 if (input != 'n')
521 printf("%c is an invalid reply. Please enter either 'y' or 'n'\n", input);
522
Bram Moolenaar442b4222010-05-24 21:34:22 +0200523 if (skip_question)
524 input = 'y';
525 else
526 {
527 rewind(stdin);
528 scanf("%c", &input);
529 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000530 switch (input)
531 {
532 case 'y':
533 case 'Y':
534 /* save the number of uninstall keys so we can know if
535 * it changed */
536 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
537 &orig_num_keys, NULL, NULL, NULL,
538 NULL, NULL, NULL, NULL);
539
Bram Moolenaar442b4222010-05-24 21:34:22 +0200540 /* Find existing .bat files before deleting them. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000541 find_bat_exe(TRUE);
542
543 /* Execute the uninstall program. Put it in double
544 * quotes if there is an embedded space. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000545 {
546 char buf[BUFSIZE];
547
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200548 if (strchr(temp_string_buffer, ' ') != NULL)
549 sprintf(buf, "\"%s\"", temp_string_buffer);
550 else
551 strcpy(buf, temp_string_buffer);
552 run_command(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000553 }
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200554
555 /* Count the number of windows with a title that match
556 * the installer, so that we can check when it's done.
557 * The uninstaller copies itself, executes the copy
558 * and exits, thus we can't wait for the process to
559 * finish. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200560 sleep(1); /* wait for uninstaller to start up */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200561 num_windows = 0;
562 EnumWindows(window_cb, 0);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200563 sleep(1); /* wait for windows to be counted */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200564 if (num_windows == 0)
565 {
566 /* Did not find the uninstaller, ask user to press
567 * Enter when done. Just in case. */
568 printf("Press Enter when the uninstaller is finished\n");
569 rewind(stdin);
570 (void)getchar();
571 }
572 else
573 {
574 printf("Waiting for the uninstaller to finish (press CTRL-C to abort).");
575 do
576 {
577 printf(".");
578 fflush(stdout);
579 num_windows = 0;
580 EnumWindows(window_cb, 0);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200581 sleep(1); /* wait for windows to be counted */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200582 } while (num_windows > 0);
583 }
584 printf("\nDone!\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000585
Bram Moolenaarfff2bee2010-05-15 13:56:02 +0200586 /* Check if an uninstall reg key was deleted.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000587 * if it was, we want to decrement key_index.
588 * if we don't do this, we will skip the key
589 * immediately after any key that we delete. */
590 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
591 &new_num_keys, NULL, NULL, NULL,
592 NULL, NULL, NULL, NULL);
593 if (new_num_keys < orig_num_keys)
594 key_index--;
595
596 input = 'y';
597 break;
598
599 case 'n':
600 case 'N':
601 /* Do not uninstall */
602 input = 'n';
603 break;
604
605 default: /* just drop through and redo the loop */
606 break;
607 }
608
609 } while (input != 'n' && input != 'y');
610
611 RegCloseKey(uninstall_key_handle);
612 }
613 }
614 RegCloseKey(key_handle);
615
616 return foundone;
617}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000618
619/*
620 * Find out information about the system.
621 */
622 static void
623inspect_system(void)
624{
625 char *p;
626 char buf[BUFSIZE];
627 FILE *fd;
628 int i;
629 int foundone;
630
631 /* This may take a little while, let the user know what we're doing. */
632 printf("Inspecting system...\n");
633
634 /*
635 * If $VIM is set, check that it's pointing to our directory.
636 */
637 p = getenv("VIM");
638 if (p != NULL && pathcmp(p, -1, installdir, runtimeidx - 1) != 0)
639 {
640 printf("------------------------------------------------------\n");
641 printf("$VIM is set to \"%s\".\n", p);
642 printf("This is different from where this version of Vim is:\n");
643 strcpy(buf, installdir);
644 *(buf + runtimeidx - 1) = NUL;
645 printf("\"%s\"\n", buf);
646 printf("You must adjust or remove the setting of $VIM,\n");
647 if (interactive)
648 {
649 printf("to be able to use this install program.\n");
650 myexit(1);
651 }
652 printf("otherwise Vim WILL NOT WORK properly!\n");
653 printf("------------------------------------------------------\n");
654 }
655
656 /*
657 * If $VIMRUNTIME is set, check that it's pointing to our runtime directory.
658 */
659 p = getenv("VIMRUNTIME");
660 if (p != NULL && pathcmp(p, -1, installdir, -1) != 0)
661 {
662 printf("------------------------------------------------------\n");
663 printf("$VIMRUNTIME is set to \"%s\".\n", p);
664 printf("This is different from where this version of Vim is:\n");
665 printf("\"%s\"\n", installdir);
666 printf("You must adjust or remove the setting of $VIMRUNTIME,\n");
667 if (interactive)
668 {
669 printf("to be able to use this install program.\n");
670 myexit(1);
671 }
672 printf("otherwise Vim WILL NOT WORK properly!\n");
673 printf("------------------------------------------------------\n");
674 }
675
676 /*
677 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
678 */
679 find_bat_exe(FALSE);
680
681 /*
682 * A .exe in the install directory may be found anyway on Windows 2000.
683 * Check for this situation and find another executable if necessary.
684 * w.briscoe@ponl.com 2001-01-20
685 */
686 foundone = 0;
687 for (i = 1; i < TARGET_COUNT; ++i)
688 {
689 findoldfile(&(targets[i].oldexe));
690 if (targets[i].oldexe != NULL)
691 foundone = 1;
692 }
693
694 if (foundone)
695 {
696 printf("Warning: Found Vim executable(s) in your $PATH:\n");
697 for (i = 1; i < TARGET_COUNT; ++i)
698 if (targets[i].oldexe != NULL)
699 printf("%s\n", targets[i].oldexe);
700 printf("It will be used instead of the version you are installing.\n");
701 printf("Please delete or rename it, or adjust your $PATH setting.\n");
702 }
703
704 /*
705 * Check if there is an existing ../_vimrc or ../.vimrc file.
706 */
707 strcpy(oldvimrc, installdir);
708 strcpy(oldvimrc + runtimeidx, "_vimrc");
709 if ((fd = fopen(oldvimrc, "r")) == NULL)
710 {
711 strcpy(oldvimrc + runtimeidx, "vimrc~1"); /* short version of .vimrc */
712 if ((fd = fopen(oldvimrc, "r")) == NULL)
713 {
714 strcpy(oldvimrc + runtimeidx, ".vimrc");
715 fd = fopen(oldvimrc, "r");
716 }
717 }
718 if (fd != NULL)
719 fclose(fd);
720 else
721 *oldvimrc = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000722}
723
724/*
725 * Add a dummy choice to avoid that the numbering changes depending on items
726 * in the environment. The user may type a number he remembered without
727 * looking.
728 */
729 static void
730add_dummy_choice(void)
731{
732 choices[choice_count].installfunc = NULL;
733 choices[choice_count].active = 0;
734 choices[choice_count].changefunc = NULL;
735 choices[choice_count].installfunc = NULL;
736 ++choice_count;
737}
738
739/***********************************************
740 * stuff for creating the batch files.
741 */
742
743/*
744 * Install the vim.bat, gvim.bat, etc. files.
745 */
746 static void
747install_bat_choice(int idx)
748{
749 char *batpath = targets[choices[idx].arg].batpath;
750 char *oldname = targets[choices[idx].arg].oldbat;
751 char *exename = targets[choices[idx].arg].exenamearg;
752 char *vimarg = targets[choices[idx].arg].exearg;
753 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754
755 if (*batpath != NUL)
756 {
757 fd = fopen(batpath, "w");
758 if (fd == NULL)
759 printf("\nERROR: Cannot open \"%s\" for writing.\n", batpath);
760 else
761 {
762 need_uninstall_entry = 1;
763
764 fprintf(fd, "@echo off\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000765 fprintf(fd, "rem -- Run Vim --\n");
766 fprintf(fd, "\n");
Bram Moolenaare609ad52016-03-28 23:05:48 +0200767 fprintf(fd, "setlocal\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000769 /* Don't use double quotes for the "set" argument, also when it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000770 * contains a space. The quotes would be included in the value
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000771 * for MSDOS and NT.
772 * The order of preference is:
773 * 1. $VIMRUNTIME/vim.exe (user preference)
774 * 2. $VIM/vim70/vim.exe (hard coded version)
775 * 3. installdir/vim.exe (hard coded install directory)
776 */
777 fprintf(fd, "set VIM_EXE_DIR=%s\n", installdir);
778 fprintf(fd, "if exist \"%%VIM%%\\%s\\%s\" set VIM_EXE_DIR=%%VIM%%\\%s\n",
779 VIM_VERSION_NODOT, exename, VIM_VERSION_NODOT);
780 fprintf(fd, "if exist \"%%VIMRUNTIME%%\\%s\" set VIM_EXE_DIR=%%VIMRUNTIME%%\n", exename);
781 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782
783 /* Give an error message when the executable could not be found. */
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000784 fprintf(fd, "if exist \"%%VIM_EXE_DIR%%\\%s\" goto havevim\n",
785 exename);
786 fprintf(fd, "echo \"%%VIM_EXE_DIR%%\\%s\" not found\n", exename);
787 fprintf(fd, "goto eof\n");
788 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 fprintf(fd, ":havevim\n");
790
791 fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
792 fprintf(fd, "set VIMARGS=\n");
793 if (*exename == 'g')
794 fprintf(fd, "set VIMNOFORK=\n");
795 fprintf(fd, ":loopstart\n");
796 fprintf(fd, "if .%%1==. goto loopend\n");
797 if (*exename == 'g')
798 {
Bram Moolenaare609ad52016-03-28 23:05:48 +0200799 fprintf(fd, "if NOT .%%1==.--nofork goto noforklongarg\n");
800 fprintf(fd, "set VIMNOFORK=1\n");
801 fprintf(fd, ":noforklongarg\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802 fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
803 fprintf(fd, "set VIMNOFORK=1\n");
804 fprintf(fd, ":noforkarg\n");
805 }
806 fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
807 fprintf(fd, "shift\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000808 fprintf(fd, "goto loopstart\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 fprintf(fd, ":loopend\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000810 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000811
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000812 fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n");
813 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000814
815 /* For gvim.exe use "start" to avoid that the console window stays
816 * open. */
817 if (*exename == 'g')
818 {
819 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
820 fprintf(fd, "start ");
821 }
822
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000823 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
824 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
825 exename, vimarg);
826 fprintf(fd, "goto eof\n");
827 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828
829 if (*exename == 'g')
830 {
831 fprintf(fd, ":nofork\n");
832 fprintf(fd, "start /w ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000833 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
834 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
835 exename, vimarg);
836 fprintf(fd, "goto eof\n");
837 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838 }
839
840 fprintf(fd, ":ntaction\n");
841 fprintf(fd, "rem for WinNT we can use %%*\n");
842
843 /* For gvim.exe use "start /b" to avoid that the console window
844 * stays open. */
845 if (*exename == 'g')
846 {
847 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
848 fprintf(fd, "start \"dummy\" /b ");
849 }
850
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000851 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
852 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n", exename, vimarg);
853 fprintf(fd, "goto eof\n");
854 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855
856 if (*exename == 'g')
857 {
858 fprintf(fd, ":noforknt\n");
859 fprintf(fd, "start \"dummy\" /b /wait ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000860 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
861 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n",
862 exename, vimarg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863 }
864
865 fprintf(fd, "\n:eof\n");
866 fprintf(fd, "set VIMARGS=\n");
867 if (*exename == 'g')
868 fprintf(fd, "set VIMNOFORK=\n");
869
870 fclose(fd);
871 printf("%s has been %s\n", batpath,
872 oldname == NULL ? "created" : "overwritten");
873 }
874 }
875}
876
877/*
878 * Make the text string for choice "idx".
879 * The format "fmt" is must have one %s item, which "arg" is used for.
880 */
881 static void
882alloc_text(int idx, char *fmt, char *arg)
883{
884 if (choices[idx].text != NULL)
885 free(choices[idx].text);
886
887 choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
888 sprintf(choices[idx].text, fmt, arg);
889}
890
891/*
892 * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
893 */
894 static void
895toggle_bat_choice(int idx)
896{
897 char *batname = targets[choices[idx].arg].batpath;
898 char *oldname = targets[choices[idx].arg].oldbat;
899
900 if (*batname == NUL)
901 {
902 alloc_text(idx, " Overwrite %s", oldname);
903 strcpy(batname, oldname);
904 }
905 else
906 {
907 alloc_text(idx, " Do NOT overwrite %s", oldname);
908 *batname = NUL;
909 }
910}
911
912/*
913 * Do some work for a batch file entry: Append the batch file name to the path
914 * and set the text for the choice.
915 */
916 static void
917set_bat_text(int idx, char *batpath, char *name)
918{
919 strcat(batpath, name);
920
921 alloc_text(idx, " Create %s", batpath);
922}
923
924/*
925 * Select a directory to write the batch file line.
926 */
927 static void
928change_bat_choice(int idx)
929{
930 char *path;
931 char *batpath;
932 char *name;
933 int n;
934 char *s;
935 char *p;
936 int count;
937 char **names = NULL;
938 int i;
939 int target = choices[idx].arg;
940
941 name = targets[target].batname;
942 batpath = targets[target].batpath;
943
944 path = getenv("PATH");
945 if (path == NULL)
946 {
947 printf("\nERROR: The variable $PATH is not set\n");
948 return;
949 }
950
951 /*
952 * first round: count number of names in path;
953 * second round: save names to names[].
954 */
955 for (;;)
956 {
957 count = 1;
958 for (p = path; *p; )
959 {
960 s = strchr(p, ';');
961 if (s == NULL)
962 s = p + strlen(p);
963 if (names != NULL)
964 {
965 names[count] = alloc((int)(s - p) + 1);
966 strncpy(names[count], p, s - p);
967 names[count][s - p] = NUL;
968 }
969 ++count;
970 p = s;
971 if (*p != NUL)
972 ++p;
973 }
974 if (names != NULL)
975 break;
976 names = alloc((int)(count + 1) * sizeof(char *));
977 }
978 names[0] = alloc(50);
979 sprintf(names[0], "Select directory to create %s in:", name);
980 names[count] = alloc(50);
981 if (choices[idx].arg == 0)
982 sprintf(names[count], "Do not create any .bat file.");
983 else
984 sprintf(names[count], "Do not create a %s file.", name);
985 n = get_choice(names, count + 1);
986
987 if (n == count)
988 {
989 /* Selected last item, don't create bat file. */
990 *batpath = NUL;
991 if (choices[idx].arg != 0)
992 alloc_text(idx, " Do NOT create %s", name);
993 }
994 else
995 {
996 /* Selected one of the paths. For the first item only keep the path,
997 * for the others append the batch file name. */
998 strcpy(batpath, names[n]);
999 add_pathsep(batpath);
1000 if (choices[idx].arg != 0)
1001 set_bat_text(idx, batpath, name);
1002 }
1003
1004 for (i = 0; i <= count; ++i)
1005 free(names[i]);
1006 free(names);
1007}
1008
1009char *bat_text_yes = "Install .bat files to use Vim at the command line:";
1010char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
1011
1012 static void
1013change_main_bat_choice(int idx)
1014{
1015 int i;
1016
1017 /* let the user select a default directory or NONE */
1018 change_bat_choice(idx);
1019
1020 if (targets[0].batpath[0] != NUL)
1021 choices[idx].text = bat_text_yes;
1022 else
1023 choices[idx].text = bat_text_no;
1024
1025 /* update the individual batch file selections */
1026 for (i = 1; i < TARGET_COUNT; ++i)
1027 {
1028 /* Only make it active when the first item has a path and the vim.exe
1029 * or gvim.exe exists (there is a changefunc then). */
1030 if (targets[0].batpath[0] != NUL
1031 && choices[idx + i].changefunc != NULL)
1032 {
1033 choices[idx + i].active = 1;
1034 if (choices[idx + i].changefunc == change_bat_choice
1035 && targets[i].batpath[0] != NUL)
1036 {
1037 strcpy(targets[i].batpath, targets[0].batpath);
1038 set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
1039 }
1040 }
1041 else
1042 choices[idx + i].active = 0;
1043 }
1044}
1045
1046/*
1047 * Initialize a choice for creating a batch file.
1048 */
1049 static void
1050init_bat_choice(int target)
1051{
1052 char *batpath = targets[target].batpath;
1053 char *oldbat = targets[target].oldbat;
1054 char *p;
1055 int i;
1056
1057 choices[choice_count].arg = target;
1058 choices[choice_count].installfunc = install_bat_choice;
1059 choices[choice_count].active = 1;
1060 choices[choice_count].text = NULL; /* will be set below */
1061 if (oldbat != NULL)
1062 {
1063 /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
1064 choices[choice_count].changefunc = toggle_bat_choice;
1065 *batpath = NUL;
1066 toggle_bat_choice(choice_count);
1067 }
1068 else
1069 {
1070 if (default_bat_dir != NULL)
1071 /* Prefer using the same path as an existing .bat file. */
1072 strcpy(batpath, default_bat_dir);
1073 else
1074 {
1075 /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
1076 * $WINDIR by default, if it's empty the first item in $PATH. */
1077 p = getenv("WINDIR");
1078 if (p != NULL && *p != NUL)
1079 strcpy(batpath, p);
1080 else
1081 {
1082 p = getenv("PATH");
1083 if (p == NULL || *p == NUL) /* "cannot happen" */
1084 strcpy(batpath, "C:/Windows");
1085 else
1086 {
1087 i = 0;
1088 while (*p != NUL && *p != ';')
1089 batpath[i++] = *p++;
1090 batpath[i] = NUL;
1091 }
1092 }
1093 }
1094 add_pathsep(batpath);
1095 set_bat_text(choice_count, batpath, targets[target].batname);
1096
1097 choices[choice_count].changefunc = change_bat_choice;
1098 }
1099 ++choice_count;
1100}
1101
1102/*
1103 * Set up the choices for installing .bat files.
1104 * For these items "arg" is the index in targets[].
1105 */
1106 static void
1107init_bat_choices(void)
1108{
1109 int i;
1110
1111 /* The first item is used to switch installing batch files on/off and
1112 * setting the default path. */
1113 choices[choice_count].text = bat_text_yes;
1114 choices[choice_count].changefunc = change_main_bat_choice;
1115 choices[choice_count].installfunc = NULL;
1116 choices[choice_count].active = 1;
1117 choices[choice_count].arg = 0;
1118 ++choice_count;
1119
1120 /* Add items for each batch file target. Only used when not disabled by
1121 * the first item. When a .exe exists, don't offer to create a .bat. */
1122 for (i = 1; i < TARGET_COUNT; ++i)
1123 if (targets[i].oldexe == NULL
1124 && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
1125 init_bat_choice(i);
1126 else
1127 add_dummy_choice();
1128}
1129
1130/*
1131 * Install the vimrc file.
1132 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001133 static void
1134install_vimrc(int idx)
1135{
1136 FILE *fd, *tfd;
1137 char *fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138
1139 /* If an old vimrc file exists, overwrite it.
1140 * Otherwise create a new one. */
1141 if (*oldvimrc != NUL)
1142 fname = oldvimrc;
1143 else
1144 fname = vimrc;
1145
1146 fd = fopen(fname, "w");
1147 if (fd == NULL)
1148 {
1149 printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
1150 return;
1151 }
1152 switch (compat_choice)
1153 {
1154 case compat_vi:
1155 fprintf(fd, "set compatible\n");
1156 break;
1157 case compat_some_enhancements:
Bram Moolenaarc73e4472016-07-29 18:33:38 +02001158 fprintf(fd, "source $VIMRUNTIME/defaults.vim\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159 break;
1160 case compat_all_enhancements:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001161 fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
1162 break;
1163 }
1164 switch (remap_choice)
1165 {
1166 case remap_no:
1167 break;
1168 case remap_win:
1169 fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
1170 break;
1171 }
1172 switch (mouse_choice)
1173 {
1174 case mouse_xterm:
1175 fprintf(fd, "behave xterm\n");
1176 break;
1177 case mouse_mswin:
1178 fprintf(fd, "behave mswin\n");
1179 break;
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02001180 case mouse_default:
1181 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001182 }
1183 if ((tfd = fopen("diff.exe", "r")) != NULL)
1184 {
1185 /* Use the diff.exe that comes with the self-extracting gvim.exe. */
1186 fclose(tfd);
1187 fprintf(fd, "\n");
1188 fprintf(fd, "set diffexpr=MyDiff()\n");
1189 fprintf(fd, "function MyDiff()\n");
1190 fprintf(fd, " let opt = '-a --binary '\n");
1191 fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
1192 fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
1193 /* Use quotes only when needed, they may cause trouble. */
1194 fprintf(fd, " let arg1 = v:fname_in\n");
1195 fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
1196 fprintf(fd, " let arg2 = v:fname_new\n");
1197 fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
1198 fprintf(fd, " let arg3 = v:fname_out\n");
1199 fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001200
1201 /* If the path has a space: When using cmd.exe (Win NT/2000/XP) put
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001202 * quotes around the diff command and rely on the default value of
1203 * shellxquote to solve the quoting problem for the whole command.
1204 *
Bram Moolenaar33aec762006-01-22 23:30:12 +00001205 * Otherwise put a double quote just before the space and at the
1206 * end of the command. Putting quotes around the whole thing
1207 * doesn't work on Win 95/98/ME. This is mostly guessed! */
Bram Moolenaar33aec762006-01-22 23:30:12 +00001208 fprintf(fd, " if $VIMRUNTIME =~ ' '\n");
1209 fprintf(fd, " if &sh =~ '\\<cmd'\n");
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001210 fprintf(fd, " if empty(&shellxquote)\n");
1211 fprintf(fd, " let l:shxq_sav = ''\n");
1212 fprintf(fd, " set shellxquote&\n");
1213 fprintf(fd, " endif\n");
1214 fprintf(fd, " let cmd = '\"' . $VIMRUNTIME . '\\diff\"'\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001215 fprintf(fd, " else\n");
1216 fprintf(fd, " let cmd = substitute($VIMRUNTIME, ' ', '\" ', '') . '\\diff\"'\n");
1217 fprintf(fd, " endif\n");
1218 fprintf(fd, " else\n");
1219 fprintf(fd, " let cmd = $VIMRUNTIME . '\\diff'\n");
1220 fprintf(fd, " endif\n");
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001221 fprintf(fd, " silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n");
1222 fprintf(fd, " if exists('l:shxq_sav')\n");
1223 fprintf(fd, " let &shellxquote=l:shxq_sav\n");
1224 fprintf(fd, " endif\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001225 fprintf(fd, "endfunction\n");
1226 fprintf(fd, "\n");
1227 }
1228 fclose(fd);
1229 printf("%s has been written\n", fname);
1230}
1231
1232 static void
1233change_vimrc_choice(int idx)
1234{
1235 if (choices[idx].installfunc != NULL)
1236 {
1237 /* Switch to NOT change or create a vimrc file. */
1238 if (*oldvimrc != NUL)
1239 alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
1240 else
1241 alloc_text(idx, "Do NOT create startup file %s", vimrc);
1242 choices[idx].installfunc = NULL;
1243 choices[idx + 1].active = 0;
1244 choices[idx + 2].active = 0;
1245 choices[idx + 3].active = 0;
1246 }
1247 else
1248 {
1249 /* Switch to change or create a vimrc file. */
1250 if (*oldvimrc != NUL)
1251 alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
1252 else
1253 alloc_text(idx, "Create startup file %s with:", vimrc);
1254 choices[idx].installfunc = install_vimrc;
1255 choices[idx + 1].active = 1;
1256 choices[idx + 2].active = 1;
1257 choices[idx + 3].active = 1;
1258 }
1259}
1260
1261/*
1262 * Change the choice how to run Vim.
1263 */
1264 static void
1265change_run_choice(int idx)
1266{
1267 compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
1268 alloc_text(idx, compat_text, compat_choices[compat_choice]);
1269}
1270
1271/*
1272 * Change the choice if keys are to be remapped.
1273 */
1274 static void
1275change_remap_choice(int idx)
1276{
1277 remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
1278 alloc_text(idx, remap_text, remap_choices[remap_choice]);
1279}
1280
1281/*
1282 * Change the choice how to select text.
1283 */
1284 static void
1285change_mouse_choice(int idx)
1286{
1287 mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
1288 alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
1289}
1290
1291 static void
1292init_vimrc_choices(void)
1293{
1294 /* set path for a new _vimrc file (also when not used) */
1295 strcpy(vimrc, installdir);
1296 strcpy(vimrc + runtimeidx, "_vimrc");
1297
1298 /* Set opposite value and then toggle it by calling change_vimrc_choice() */
1299 if (*oldvimrc == NUL)
1300 choices[choice_count].installfunc = NULL;
1301 else
1302 choices[choice_count].installfunc = install_vimrc;
1303 choices[choice_count].text = NULL;
1304 change_vimrc_choice(choice_count);
1305 choices[choice_count].changefunc = change_vimrc_choice;
1306 choices[choice_count].active = 1;
1307 ++choice_count;
1308
1309 /* default way to run Vim */
1310 alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
1311 choices[choice_count].changefunc = change_run_choice;
1312 choices[choice_count].installfunc = NULL;
1313 choices[choice_count].active = (*oldvimrc == NUL);
1314 ++choice_count;
1315
1316 /* Whether to remap keys */
1317 alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
1318 choices[choice_count].changefunc = change_remap_choice;
Bram Moolenaar945ec092016-06-08 21:17:43 +02001319 choices[choice_count].installfunc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001320 choices[choice_count].active = (*oldvimrc == NUL);
1321 ++choice_count;
1322
1323 /* default way to use the mouse */
1324 alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
1325 choices[choice_count].changefunc = change_mouse_choice;
Bram Moolenaar945ec092016-06-08 21:17:43 +02001326 choices[choice_count].installfunc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001327 choices[choice_count].active = (*oldvimrc == NUL);
1328 ++choice_count;
1329}
1330
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001331 static LONG
1332reg_create_key(
1333 HKEY root,
1334 const char *subkey,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001335 PHKEY phKey,
1336 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001337{
1338 DWORD disp;
1339
1340 *phKey = NULL;
1341 return RegCreateKeyEx(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001342 root, subkey,
1343 0, NULL, REG_OPTION_NON_VOLATILE,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001344 flag | KEY_WRITE,
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001345 NULL, phKey, &disp);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001346}
1347
1348 static LONG
1349reg_set_string_value(
1350 HKEY hKey,
1351 const char *value_name,
1352 const char *data)
1353{
1354 return RegSetValueEx(hKey, value_name, 0, REG_SZ,
1355 (LPBYTE)data, (DWORD)(1 + strlen(data)));
1356}
1357
1358 static LONG
1359reg_create_key_and_value(
1360 HKEY hRootKey,
1361 const char *subkey,
1362 const char *value_name,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001363 const char *data,
1364 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001365{
1366 HKEY hKey;
Bram Moolenaar6199d432017-10-14 19:05:44 +02001367 LONG lRet = reg_create_key(hRootKey, subkey, &hKey, flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001368
1369 if (ERROR_SUCCESS == lRet)
1370 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001371 lRet = reg_set_string_value(hKey, value_name, data);
1372 RegCloseKey(hKey);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001373 }
1374 return lRet;
1375}
1376
1377 static LONG
1378register_inproc_server(
1379 HKEY hRootKey,
1380 const char *clsid,
1381 const char *extname,
1382 const char *module,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001383 const char *threading_model,
1384 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001385{
1386 CHAR subkey[BUFSIZE];
1387 LONG lRet;
1388
1389 sprintf(subkey, "CLSID\\%s", clsid);
Bram Moolenaar6199d432017-10-14 19:05:44 +02001390 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, extname, flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001391 if (ERROR_SUCCESS == lRet)
1392 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001393 sprintf(subkey, "CLSID\\%s\\InProcServer32", clsid);
Bram Moolenaar6199d432017-10-14 19:05:44 +02001394 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, module, flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001395 if (ERROR_SUCCESS == lRet)
1396 {
1397 lRet = reg_create_key_and_value(hRootKey, subkey,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001398 "ThreadingModel", threading_model, flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001399 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001400 }
1401 return lRet;
1402}
1403
1404 static LONG
1405register_shellex(
1406 HKEY hRootKey,
1407 const char *clsid,
1408 const char *name,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001409 const char *exe_path,
1410 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001411{
1412 LONG lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001413 hRootKey,
1414 "*\\shellex\\ContextMenuHandlers\\gvim",
1415 NULL,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001416 clsid,
1417 flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001418
1419 if (ERROR_SUCCESS == lRet)
1420 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001421 lRet = reg_create_key_and_value(
1422 HKEY_LOCAL_MACHINE,
1423 "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1424 clsid,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001425 name,
1426 flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001427
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001428 if (ERROR_SUCCESS == lRet)
1429 {
1430 lRet = reg_create_key_and_value(
1431 HKEY_LOCAL_MACHINE,
1432 "Software\\Vim\\Gvim",
1433 "path",
Bram Moolenaar6199d432017-10-14 19:05:44 +02001434 exe_path,
1435 flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001436 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001437 }
1438 return lRet;
1439}
1440
1441 static LONG
1442register_openwith(
1443 HKEY hRootKey,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001444 const char *exe_path,
1445 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001446{
Bram Moolenaar78050042010-07-31 20:53:54 +02001447 char exe_cmd[BUFSIZE];
1448 LONG lRet;
1449
Bram Moolenaarbbdcb482010-08-02 20:45:27 +02001450 sprintf(exe_cmd, "\"%s\" \"%%1\"", exe_path);
Bram Moolenaar78050042010-07-31 20:53:54 +02001451 lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001452 hRootKey,
1453 "Applications\\gvim.exe\\shell\\edit\\command",
1454 NULL,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001455 exe_cmd,
1456 flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001457
1458 if (ERROR_SUCCESS == lRet)
1459 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001460 int i;
1461 static const char *openwith[] = {
1462 ".htm\\OpenWithList\\gvim.exe",
1463 ".vim\\OpenWithList\\gvim.exe",
1464 "*\\OpenWithList\\gvim.exe",
1465 };
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001466
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001467 for (i = 0; ERROR_SUCCESS == lRet
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001468 && i < sizeof(openwith) / sizeof(openwith[0]); i++)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001469 {
Bram Moolenaar6199d432017-10-14 19:05:44 +02001470 lRet = reg_create_key_and_value(hRootKey, openwith[i], NULL, "", flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001471 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001472 }
1473
1474 return lRet;
1475}
1476
1477 static LONG
1478register_uninstall(
1479 HKEY hRootKey,
1480 const char *appname,
1481 const char *display_name,
1482 const char *uninstall_string)
1483{
1484 LONG lRet = reg_create_key_and_value(hRootKey, appname,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001485 "DisplayName", display_name, KEY_WOW64_64KEY);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001486
1487 if (ERROR_SUCCESS == lRet)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001488 lRet = reg_create_key_and_value(hRootKey, appname,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001489 "UninstallString", uninstall_string, KEY_WOW64_64KEY);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001490 return lRet;
1491}
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001492
Bram Moolenaar071d4272004-06-13 20:20:40 +00001493/*
1494 * Add some entries to the registry:
1495 * - to add "Edit with Vim" to the context * menu
1496 * - to add Vim to the "Open with..." list
1497 * - to uninstall Vim
1498 */
1499/*ARGSUSED*/
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001500 static int
Bram Moolenaar071d4272004-06-13 20:20:40 +00001501install_registry(void)
1502{
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001503 LONG lRet = ERROR_SUCCESS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001504 const char *vim_ext_ThreadingModel = "Apartment";
1505 const char *vim_ext_name = "Vim Shell Extension";
1506 const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001507 char vim_exe_path[BUFSIZE];
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001508 char display_name[BUFSIZE];
1509 char uninstall_string[BUFSIZE];
Bram Moolenaar6199d432017-10-14 19:05:44 +02001510 int i;
1511 int loop_count = is_64bit_os() ? 2 : 1;
1512 DWORD flag;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001513
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001514 sprintf(vim_exe_path, "%s\\gvim.exe", installdir);
1515
1516 if (install_popup)
1517 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001518 char bufg[BUFSIZE];
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001519
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001520 printf("Creating \"Edit with Vim\" popup menu entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001521
Bram Moolenaar6199d432017-10-14 19:05:44 +02001522 for (i = 0; i < loop_count; i++)
1523 {
1524 if (i == 0)
1525 {
1526 sprintf(bufg, "%s\\" GVIMEXT32_PATH, installdir);
1527 flag = KEY_WOW64_32KEY;
1528 }
1529 else
1530 {
1531 sprintf(bufg, "%s\\" GVIMEXT64_PATH, installdir);
1532 flag = KEY_WOW64_64KEY;
1533 }
1534
1535 lRet = register_inproc_server(
1536 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name,
1537 bufg, vim_ext_ThreadingModel, flag);
1538 if (ERROR_SUCCESS != lRet)
1539 return FAIL;
1540 lRet = register_shellex(
1541 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name,
1542 vim_exe_path, flag);
1543 if (ERROR_SUCCESS != lRet)
1544 return FAIL;
1545 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001546 }
1547
1548 if (install_openwith)
1549 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001550 printf("Creating \"Open with ...\" list entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001551
Bram Moolenaar6199d432017-10-14 19:05:44 +02001552 for (i = 0; i < loop_count; i++)
1553 {
1554 if (i == 0)
1555 flag = KEY_WOW64_32KEY;
1556 else
1557 flag = KEY_WOW64_64KEY;
1558
1559 lRet = register_openwith(HKEY_CLASSES_ROOT, vim_exe_path, flag);
1560 if (ERROR_SUCCESS != lRet)
1561 return FAIL;
1562 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001563 }
1564
1565 printf("Creating an uninstall entry\n");
1566
1567 /* For the NSIS installer use the generated uninstaller. */
1568 if (interactive)
1569 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001570 sprintf(display_name, "Vim " VIM_VERSION_SHORT);
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001571 sprintf(uninstall_string, "%s\\uninstal.exe", installdir);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001572 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001573 else
1574 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001575 sprintf(display_name, "Vim " VIM_VERSION_SHORT " (self-installing)");
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001576 sprintf(uninstall_string, "%s\\uninstall-gui.exe", installdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001577 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001578
1579 lRet = register_uninstall(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001580 HKEY_LOCAL_MACHINE,
1581 "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT,
1582 display_name,
1583 uninstall_string);
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001584 if (ERROR_SUCCESS != lRet)
1585 return FAIL;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001586
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001587 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001588}
1589
1590 static void
1591change_popup_choice(int idx)
1592{
1593 if (install_popup == 0)
1594 {
1595 choices[idx].text = "Install an entry for Vim in the popup menu for the right\n mouse button so that you can edit any file with Vim";
1596 install_popup = 1;
1597 }
1598 else
1599 {
1600 choices[idx].text = "Do NOT install an entry for Vim in the popup menu for the\n right mouse button to edit any file with Vim";
1601 install_popup = 0;
1602 }
1603}
1604
1605/*
1606 * Only add the choice for the popup menu entry when gvim.exe was found and
1607 * both gvimext.dll and regedit.exe exist.
1608 */
1609 static void
1610init_popup_choice(void)
1611{
1612 struct stat st;
1613
1614 if (has_gvim
Bram Moolenaar6199d432017-10-14 19:05:44 +02001615 && (stat(GVIMEXT32_PATH, &st) >= 0
1616 || stat(GVIMEXT64_PATH, &st) >= 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001617 {
1618 choices[choice_count].changefunc = change_popup_choice;
1619 choices[choice_count].installfunc = NULL;
1620 choices[choice_count].active = 1;
1621 change_popup_choice(choice_count); /* set the text */
1622 ++choice_count;
1623 }
1624 else
1625 add_dummy_choice();
1626}
1627
1628 static void
1629change_openwith_choice(int idx)
1630{
1631 if (install_openwith == 0)
1632 {
1633 choices[idx].text = "Add Vim to the \"Open With...\" list in the popup menu for the right\n mouse button so that you can edit any file with Vim";
1634 install_openwith = 1;
1635 }
1636 else
1637 {
1638 choices[idx].text = "Do NOT add Vim to the \"Open With...\" list in the popup menu for the\n right mouse button to edit any file with Vim";
1639 install_openwith = 0;
1640 }
1641}
1642
1643/*
1644 * Only add the choice for the open-with menu entry when gvim.exe was found
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001645 * and regedit.exe exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001646 */
1647 static void
1648init_openwith_choice(void)
1649{
Bram Moolenaar6199d432017-10-14 19:05:44 +02001650 if (has_gvim)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001651 {
1652 choices[choice_count].changefunc = change_openwith_choice;
1653 choices[choice_count].installfunc = NULL;
1654 choices[choice_count].active = 1;
1655 change_openwith_choice(choice_count); /* set the text */
1656 ++choice_count;
1657 }
1658 else
1659 add_dummy_choice();
1660}
1661
Bram Moolenaar071d4272004-06-13 20:20:40 +00001662/* create_shortcut
1663 *
1664 * Create a shell link.
1665 *
1666 * returns 0 on failure, non-zero on successful completion.
1667 *
1668 * NOTE: Currently untested with mingw.
1669 */
1670 int
1671create_shortcut(
1672 const char *shortcut_name,
1673 const char *iconfile_path,
1674 int iconindex,
1675 const char *shortcut_target,
1676 const char *shortcut_args,
1677 const char *workingdir
1678 )
1679{
1680 IShellLink *shelllink_ptr;
1681 HRESULT hres;
1682 IPersistFile *persistfile_ptr;
1683
1684 /* Initialize COM library */
1685 hres = CoInitialize(NULL);
1686 if (!SUCCEEDED(hres))
1687 {
1688 printf("Error: Could not open the COM library. Not creating shortcut.\n");
1689 return FAIL;
1690 }
1691
1692 /* Instantiate a COM object for the ShellLink, store a pointer to it
1693 * in shelllink_ptr. */
1694 hres = CoCreateInstance(&CLSID_ShellLink,
1695 NULL,
1696 CLSCTX_INPROC_SERVER,
1697 &IID_IShellLink,
1698 (void **) &shelllink_ptr);
1699
1700 if (SUCCEEDED(hres)) /* If the instantiation was successful... */
1701 {
1702 /* ...Then build a PersistFile interface for the ShellLink so we can
1703 * save it as a file after we build it. */
1704 hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
1705 &IID_IPersistFile, (void **) &persistfile_ptr);
1706
1707 if (SUCCEEDED(hres))
1708 {
1709 wchar_t wsz[BUFSIZE];
1710
1711 /* translate the (possibly) multibyte shortcut filename to windows
1712 * Unicode so it can be used as a file name.
1713 */
1714 MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
1715
1716 /* set the attributes */
1717 shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
1718 shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
1719 workingdir);
1720 shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
1721 iconfile_path, iconindex);
1722 shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
1723
1724 /* save the shortcut to a file and return the PersistFile object*/
1725 persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
1726 persistfile_ptr->lpVtbl->Release(persistfile_ptr);
1727 }
1728 else
1729 {
1730 printf("QueryInterface Error\n");
1731 return FAIL;
1732 }
1733
1734 /* Return the ShellLink object */
1735 shelllink_ptr->lpVtbl->Release(shelllink_ptr);
1736 }
1737 else
1738 {
1739 printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
1740 return FAIL;
1741 }
1742
1743 return OK;
1744}
1745
1746/*
1747 * Build a path to where we will put a specified link.
1748 *
1749 * Return 0 on error, non-zero on success
1750 */
1751 int
1752build_link_name(
1753 char *link_path,
1754 const char *link_name,
1755 const char *shell_folder_name)
1756{
1757 char shell_folder_path[BUFSIZE];
1758
1759 if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
1760 {
1761 printf("An error occurred while attempting to find the path to %s.\n",
1762 shell_folder_name);
1763 return FAIL;
1764 }
1765
1766 /* Make sure the directory exists (create Start Menu\Programs\Vim).
1767 * Ignore errors if it already exists. */
1768 vim_mkdir(shell_folder_path, 0755);
1769
1770 /* build the path to the shortcut and the path to gvim.exe */
1771 sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
1772
1773 return OK;
1774}
1775
1776 static int
1777build_shortcut(
1778 const char *name, /* Name of the shortcut */
1779 const char *exename, /* Name of the executable (e.g., vim.exe) */
1780 const char *args,
1781 const char *shell_folder,
1782 const char *workingdir)
1783{
1784 char executable_path[BUFSIZE];
1785 char link_name[BUFSIZE];
1786
1787 sprintf(executable_path, "%s\\%s", installdir, exename);
1788
1789 if (build_link_name(link_name, name, shell_folder) == FAIL)
1790 {
1791 printf("An error has occurred. A shortcut to %s will not be created %s.\n",
1792 name,
1793 *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
1794 return FAIL;
1795 }
1796
1797 /* Create the shortcut: */
1798 return create_shortcut(link_name, executable_path, 0,
1799 executable_path, args, workingdir);
1800}
1801
1802/*
1803 * We used to use "homedir" as the working directory, but that is a bad choice
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001804 * on multi-user systems. However, not specifying a directory results in the
1805 * current directory to be c:\Windows\system32 on Windows 7. Use environment
1806 * variables instead.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001807 */
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001808#define WORKDIR "%HOMEDRIVE%%HOMEPATH%"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001809
1810/*
1811 * Create shortcut(s) in the Start Menu\Programs\Vim folder.
1812 */
1813 static void
1814install_start_menu(int idx)
1815{
1816 need_uninstall_entry = 1;
1817 printf("Creating start menu\n");
1818 if (has_vim)
1819 {
1820 if (build_shortcut("Vim", "vim.exe", "",
1821 VIM_STARTMENU, WORKDIR) == FAIL)
1822 return;
1823 if (build_shortcut("Vim Read-only", "vim.exe", "-R",
1824 VIM_STARTMENU, WORKDIR) == FAIL)
1825 return;
1826 if (build_shortcut("Vim Diff", "vim.exe", "-d",
1827 VIM_STARTMENU, WORKDIR) == FAIL)
1828 return;
1829 }
1830 if (has_gvim)
1831 {
1832 if (build_shortcut("gVim", "gvim.exe", "",
1833 VIM_STARTMENU, WORKDIR) == FAIL)
1834 return;
1835 if (build_shortcut("gVim Easy", "gvim.exe", "-y",
1836 VIM_STARTMENU, WORKDIR) == FAIL)
1837 return;
1838 if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
1839 VIM_STARTMENU, WORKDIR) == FAIL)
1840 return;
1841 if (build_shortcut("gVim Diff", "gvim.exe", "-d",
1842 VIM_STARTMENU, WORKDIR) == FAIL)
1843 return;
1844 }
1845 if (build_shortcut("Uninstall",
1846 interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
1847 VIM_STARTMENU, installdir) == FAIL)
1848 return;
1849 /* For Windows NT the working dir of the vimtutor.bat must be right,
1850 * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
1851 if (build_shortcut("Vim tutor", "vimtutor.bat", "",
1852 VIM_STARTMENU, installdir) == FAIL)
1853 return;
1854 if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
1855 VIM_STARTMENU, WORKDIR) == FAIL)
1856 return;
1857 {
1858 char shell_folder_path[BUFSIZE];
1859
1860 /* Creating the URL shortcut works a bit differently... */
1861 if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
1862 {
1863 printf("Finding the path of the Start menu failed\n");
1864 return ;
1865 }
1866 add_pathsep(shell_folder_path);
1867 strcat(shell_folder_path, "Vim Online.url");
1868 if (!WritePrivateProfileString("InternetShortcut", "URL",
1869 "http://vim.sf.net/", shell_folder_path))
1870 {
1871 printf("Creating the Vim online URL failed\n");
1872 return;
1873 }
1874 }
1875}
1876
1877 static void
1878toggle_startmenu_choice(int idx)
1879{
1880 if (choices[idx].installfunc == NULL)
1881 {
1882 choices[idx].installfunc = install_start_menu;
1883 choices[idx].text = "Add Vim to the Start menu";
1884 }
1885 else
1886 {
1887 choices[idx].installfunc = NULL;
1888 choices[idx].text = "Do NOT add Vim to the Start menu";
1889 }
1890}
1891
1892/*
1893 * Function to actually create the shortcuts
1894 *
1895 * Currently I am supplying no working directory to the shortcut. This
1896 * means that the initial working dir will be:
1897 * - the location of the shortcut if no file is supplied
1898 * - the location of the file being edited if a file is supplied (ie via
1899 * drag and drop onto the shortcut).
1900 */
1901 void
1902install_shortcut_gvim(int idx)
1903{
1904 /* Create shortcut(s) on the desktop */
1905 if (choices[idx].arg)
1906 {
1907 (void)build_shortcut(icon_names[0], "gvim.exe",
1908 "", "desktop", WORKDIR);
1909 need_uninstall_entry = 1;
1910 }
1911}
1912
1913 void
1914install_shortcut_evim(int idx)
1915{
1916 if (choices[idx].arg)
1917 {
1918 (void)build_shortcut(icon_names[1], "gvim.exe",
1919 "-y", "desktop", WORKDIR);
1920 need_uninstall_entry = 1;
1921 }
1922}
1923
1924 void
1925install_shortcut_gview(int idx)
1926{
1927 if (choices[idx].arg)
1928 {
1929 (void)build_shortcut(icon_names[2], "gvim.exe",
1930 "-R", "desktop", WORKDIR);
1931 need_uninstall_entry = 1;
1932 }
1933}
1934
1935 void
1936toggle_shortcut_choice(int idx)
1937{
1938 char *arg;
1939
1940 if (choices[idx].installfunc == install_shortcut_gvim)
1941 arg = "gVim";
1942 else if (choices[idx].installfunc == install_shortcut_evim)
1943 arg = "gVim Easy";
1944 else
1945 arg = "gVim Read-only";
1946 if (choices[idx].arg)
1947 {
1948 choices[idx].arg = 0;
1949 alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
1950 }
1951 else
1952 {
1953 choices[idx].arg = 1;
1954 alloc_text(idx, "Create a desktop icon for %s", arg);
1955 }
1956}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001957
1958 static void
1959init_startmenu_choice(void)
1960{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001961 /* Start menu */
1962 choices[choice_count].changefunc = toggle_startmenu_choice;
1963 choices[choice_count].installfunc = NULL;
1964 choices[choice_count].active = 1;
1965 toggle_startmenu_choice(choice_count); /* set the text */
1966 ++choice_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001967}
1968
1969/*
1970 * Add the choice for the desktop shortcuts.
1971 */
1972 static void
1973init_shortcut_choices(void)
1974{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001975 /* Shortcut to gvim */
1976 choices[choice_count].text = NULL;
1977 choices[choice_count].arg = 0;
1978 choices[choice_count].active = has_gvim;
1979 choices[choice_count].changefunc = toggle_shortcut_choice;
1980 choices[choice_count].installfunc = install_shortcut_gvim;
1981 toggle_shortcut_choice(choice_count);
1982 ++choice_count;
1983
1984 /* Shortcut to evim */
1985 choices[choice_count].text = NULL;
1986 choices[choice_count].arg = 0;
1987 choices[choice_count].active = has_gvim;
1988 choices[choice_count].changefunc = toggle_shortcut_choice;
1989 choices[choice_count].installfunc = install_shortcut_evim;
1990 toggle_shortcut_choice(choice_count);
1991 ++choice_count;
1992
1993 /* Shortcut to gview */
1994 choices[choice_count].text = NULL;
1995 choices[choice_count].arg = 0;
1996 choices[choice_count].active = has_gvim;
1997 choices[choice_count].changefunc = toggle_shortcut_choice;
1998 choices[choice_count].installfunc = install_shortcut_gview;
1999 toggle_shortcut_choice(choice_count);
2000 ++choice_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002001}
2002
Bram Moolenaar071d4272004-06-13 20:20:40 +00002003/*
2004 * Attempt to register OLE for Vim.
2005 */
2006 static void
2007install_OLE_register(void)
2008{
2009 char register_command_string[BUFSIZE + 30];
2010
2011 printf("\n--- Attempting to register Vim with OLE ---\n");
2012 printf("(There is no message whether this works or not.)\n");
2013
Bram Moolenaar071d4272004-06-13 20:20:40 +00002014 sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002015 system(register_command_string);
2016}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002017
2018/*
2019 * Remove the last part of directory "path[]" to get its parent, and put the
2020 * result in "to[]".
2021 */
2022 static void
2023dir_remove_last(const char *path, char to[BUFSIZE])
2024{
2025 char c;
2026 long last_char_to_copy;
2027 long path_length = strlen(path);
2028
2029 /* skip the last character just in case it is a '\\' */
2030 last_char_to_copy = path_length - 2;
2031 c = path[last_char_to_copy];
2032
2033 while (c != '\\')
2034 {
2035 last_char_to_copy--;
2036 c = path[last_char_to_copy];
2037 }
2038
2039 strncpy(to, path, (size_t)last_char_to_copy);
2040 to[last_char_to_copy] = NUL;
2041}
2042
2043 static void
2044set_directories_text(int idx)
2045{
2046 if (vimfiles_dir_choice == (int)vimfiles_dir_none)
2047 alloc_text(idx, "Do NOT create plugin directories%s", "");
2048 else
2049 alloc_text(idx, "Create plugin directories: %s",
2050 vimfiles_dir_choices[vimfiles_dir_choice]);
2051}
2052
2053/*
2054 * Change the directory that the vim plugin directories will be created in:
2055 * $HOME, $VIM or nowhere.
2056 */
2057 static void
2058change_directories_choice(int idx)
2059{
2060 int choice_count = TABLE_SIZE(vimfiles_dir_choices);
2061
2062 /* Don't offer the $HOME choice if $HOME isn't set. */
2063 if (getenv("HOME") == NULL)
2064 --choice_count;
2065 vimfiles_dir_choice = get_choice(vimfiles_dir_choices, choice_count);
2066 set_directories_text(idx);
2067}
2068
2069/*
2070 * Create the plugin directories...
2071 */
2072/*ARGSUSED*/
2073 static void
2074install_vimfilesdir(int idx)
2075{
2076 int i;
2077 char *p;
2078 char vimdir_path[BUFSIZE];
2079 char vimfiles_path[BUFSIZE];
2080 char tmp_dirname[BUFSIZE];
2081
2082 /* switch on the location that the user wants the plugin directories
2083 * built in */
2084 switch (vimfiles_dir_choice)
2085 {
2086 case vimfiles_dir_vim:
2087 {
2088 /* Go to the %VIM% directory - check env first, then go one dir
2089 * below installdir if there is no %VIM% environment variable.
2090 * The accuracy of $VIM is checked in inspect_system(), so we
2091 * can be sure it is ok to use here. */
2092 p = getenv("VIM");
2093 if (p == NULL) /* No $VIM in path */
2094 dir_remove_last(installdir, vimdir_path);
2095 else
2096 strcpy(vimdir_path, p);
2097 break;
2098 }
2099 case vimfiles_dir_home:
2100 {
2101 /* Find the $HOME directory. Its existence was already checked. */
2102 p = getenv("HOME");
2103 if (p == NULL)
2104 {
2105 printf("Internal error: $HOME is NULL\n");
2106 p = "c:\\";
2107 }
2108 strcpy(vimdir_path, p);
2109 break;
2110 }
2111 case vimfiles_dir_none:
2112 {
2113 /* Do not create vim plugin directory */
2114 return;
2115 }
2116 }
2117
2118 /* Now, just create the directory. If it already exists, it will fail
2119 * silently. */
2120 sprintf(vimfiles_path, "%s\\vimfiles", vimdir_path);
2121 vim_mkdir(vimfiles_path, 0755);
2122
2123 printf("Creating the following directories in \"%s\":\n", vimfiles_path);
2124 for (i = 0; i < TABLE_SIZE(vimfiles_subdirs); i++)
2125 {
2126 sprintf(tmp_dirname, "%s\\%s", vimfiles_path, vimfiles_subdirs[i]);
2127 printf(" %s", vimfiles_subdirs[i]);
2128 vim_mkdir(tmp_dirname, 0755);
2129 }
2130 printf("\n");
2131}
2132
2133/*
2134 * Add the creation of runtime files to the setup sequence.
2135 */
2136 static void
2137init_directories_choice(void)
2138{
2139 struct stat st;
2140 char tmp_dirname[BUFSIZE];
2141 char *p;
2142
2143 choices[choice_count].text = alloc(150);
2144 choices[choice_count].changefunc = change_directories_choice;
2145 choices[choice_count].installfunc = install_vimfilesdir;
2146 choices[choice_count].active = 1;
2147
2148 /* Check if the "compiler" directory already exists. That's a good
2149 * indication that the plugin directories were already created. */
2150 if (getenv("HOME") != NULL)
2151 {
2152 vimfiles_dir_choice = (int)vimfiles_dir_home;
2153 sprintf(tmp_dirname, "%s\\vimfiles\\compiler", getenv("HOME"));
2154 if (stat(tmp_dirname, &st) == 0)
2155 vimfiles_dir_choice = (int)vimfiles_dir_none;
2156 }
2157 else
2158 {
2159 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2160 p = getenv("VIM");
2161 if (p == NULL) /* No $VIM in path, use the install dir */
2162 dir_remove_last(installdir, tmp_dirname);
2163 else
2164 strcpy(tmp_dirname, p);
2165 strcat(tmp_dirname, "\\vimfiles\\compiler");
2166 if (stat(tmp_dirname, &st) == 0)
2167 vimfiles_dir_choice = (int)vimfiles_dir_none;
2168 }
2169
2170 set_directories_text(choice_count);
2171 ++choice_count;
2172}
2173
2174/*
2175 * Setup the choices and the default values.
2176 */
2177 static void
2178setup_choices(void)
2179{
2180 /* install the batch files */
2181 init_bat_choices();
2182
2183 /* (over) write _vimrc file */
2184 init_vimrc_choices();
2185
2186 /* Whether to add Vim to the popup menu */
2187 init_popup_choice();
2188
2189 /* Whether to add Vim to the "Open With..." menu */
2190 init_openwith_choice();
2191
2192 /* Whether to add Vim to the Start Menu. */
2193 init_startmenu_choice();
2194
2195 /* Whether to add shortcuts to the Desktop. */
2196 init_shortcut_choices();
2197
2198 /* Whether to create the runtime directories. */
2199 init_directories_choice();
2200}
2201
2202 static void
2203print_cmd_line_help(void)
2204{
2205 printf("Vim installer non-interactive command line arguments:\n");
2206 printf("\n");
2207 printf("-create-batfiles [vim gvim evim view gview vimdiff gvimdiff]\n");
2208 printf(" Create .bat files for Vim variants in the Windows directory.\n");
2209 printf("-create-vimrc\n");
2210 printf(" Create a default _vimrc file if one does not already exist.\n");
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02002211 printf("-vimrc-remap [no|win]\n");
2212 printf(" Remap keys when creating a default _vimrc file.\n");
2213 printf("-vimrc-behave [unix|mswin|default]\n");
2214 printf(" Set mouse behavior when creating a default _vimrc file.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002215 printf("-install-popup\n");
2216 printf(" Install the Edit-with-Vim context menu entry\n");
2217 printf("-install-openwith\n");
2218 printf(" Add Vim to the \"Open With...\" context menu list\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002219 printf("-add-start-menu");
2220 printf(" Add Vim to the start menu\n");
2221 printf("-install-icons");
2222 printf(" Create icons for gVim executables on the desktop\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002223 printf("-create-directories [vim|home]\n");
2224 printf(" Create runtime directories to drop plugins into; in the $VIM\n");
2225 printf(" or $HOME directory\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002226 printf("-register-OLE");
Bram Moolenaarce0842a2005-07-18 21:58:11 +00002227 printf(" Ignored\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002228 printf("\n");
2229}
2230
2231/*
2232 * Setup installation choices based on command line switches
2233 */
2234 static void
2235command_line_setup_choices(int argc, char **argv)
2236{
2237 int i, j;
2238
2239 for (i = 1; i < argc; i++)
2240 {
2241 if (strcmp(argv[i], "-create-batfiles") == 0)
2242 {
2243 if (i + 1 == argc)
2244 continue;
2245 while (argv[i + 1][0] != '-' && i < argc)
2246 {
2247 i++;
2248 for (j = 1; j < TARGET_COUNT; ++j)
2249 if ((targets[j].exenamearg[0] == 'g' ? has_gvim : has_vim)
2250 && strcmp(argv[i], targets[j].name) == 0)
2251 {
2252 init_bat_choice(j);
2253 break;
2254 }
2255 if (j == TARGET_COUNT)
2256 printf("%s is not a valid choice for -create-batfiles\n",
2257 argv[i]);
2258
2259 if (i + 1 == argc)
2260 break;
2261 }
2262 }
2263 else if (strcmp(argv[i], "-create-vimrc") == 0)
2264 {
2265 /* Setup default vimrc choices. If there is already a _vimrc file,
2266 * it will NOT be overwritten.
2267 */
2268 init_vimrc_choices();
2269 }
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02002270 else if (strcmp(argv[i], "-vimrc-remap") == 0)
2271 {
2272 if (i + 1 == argc)
2273 break;
2274 i++;
2275 if (strcmp(argv[i], "no") == 0)
2276 remap_choice = remap_no;
2277 else if (strcmp(argv[i], "win") == 0)
2278 remap_choice = remap_win;
2279 }
2280 else if (strcmp(argv[i], "-vimrc-behave") == 0)
2281 {
2282 if (i + 1 == argc)
2283 break;
2284 i++;
2285 if (strcmp(argv[i], "unix") == 0)
2286 mouse_choice = mouse_xterm;
2287 else if (strcmp(argv[i], "mswin") == 0)
2288 mouse_choice = mouse_mswin;
2289 else if (strcmp(argv[i], "default") == 0)
2290 mouse_choice = mouse_default;
2291 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002292 else if (strcmp(argv[i], "-install-popup") == 0)
2293 {
2294 init_popup_choice();
2295 }
2296 else if (strcmp(argv[i], "-install-openwith") == 0)
2297 {
2298 init_openwith_choice();
2299 }
2300 else if (strcmp(argv[i], "-add-start-menu") == 0)
2301 {
2302 init_startmenu_choice();
2303 }
2304 else if (strcmp(argv[i], "-install-icons") == 0)
2305 {
2306 init_shortcut_choices();
2307 }
2308 else if (strcmp(argv[i], "-create-directories") == 0)
2309 {
2310 init_directories_choice();
2311 if (argv[i + 1][0] != '-')
2312 {
2313 i++;
2314 if (strcmp(argv[i], "vim") == 0)
2315 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2316 else if (strcmp(argv[i], "home") == 0)
2317 {
2318 if (getenv("HOME") == NULL) /* No $HOME in environment */
2319 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2320 else
2321 vimfiles_dir_choice = (int)vimfiles_dir_home;
2322 }
2323 else
2324 {
2325 printf("Unknown argument for -create-directories: %s\n",
2326 argv[i]);
2327 print_cmd_line_help();
2328 }
2329 }
2330 else /* No choice specified, default to vim directory */
2331 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2332 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002333 else if (strcmp(argv[i], "-register-OLE") == 0)
2334 {
2335 /* This is always done when gvim is found */
2336 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002337 else /* Unknown switch */
2338 {
2339 printf("Got unknown argument argv[%d] = %s\n", i, argv[i]);
2340 print_cmd_line_help();
2341 }
2342 }
2343}
2344
2345
2346/*
2347 * Show a few screens full of helpful information.
2348 */
2349 static void
2350show_help(void)
2351{
2352 static char *(items[]) =
2353 {
2354"Installing .bat files\n"
2355"---------------------\n"
2356"The vim.bat file is written in one of the directories in $PATH.\n"
2357"This makes it possible to start Vim from the command line.\n"
2358"If vim.exe can be found in $PATH, the choice for vim.bat will not be\n"
2359"present. It is assumed you will use the existing vim.exe.\n"
2360"If vim.bat can already be found in $PATH this is probably for an old\n"
2361"version of Vim (but this is not checked!). You can overwrite it.\n"
2362"If no vim.bat already exists, you can select one of the directories in\n"
2363"$PATH for creating the batch file, or disable creating a vim.bat file.\n"
2364"\n"
2365"If you choose not to create the vim.bat file, Vim can still be executed\n"
2366"in other ways, but not from the command line.\n"
2367"\n"
2368"The same applies to choices for gvim, evim, (g)view, and (g)vimdiff.\n"
2369"The first item can be used to change the path for all of them.\n"
2370,
2371"Creating a _vimrc file\n"
2372"----------------------\n"
2373"The _vimrc file is used to set options for how Vim behaves.\n"
2374"The install program can create a _vimrc file with a few basic choices.\n"
2375"You can edit this file later to tune your preferences.\n"
2376"If you already have a _vimrc or .vimrc file it can be overwritten.\n"
2377"Don't do that if you have made changes to it.\n"
2378,
2379"Vim features\n"
2380"------------\n"
2381"(this choice is only available when creating a _vimrc file)\n"
2382"1. Vim can run in Vi-compatible mode. Many nice Vim features are then\n"
2383" disabled. In the not-Vi-compatible mode Vim is still mostly Vi\n"
2384" compatible, but adds nice features like multi-level undo. Only\n"
2385" choose Vi-compatible if you really need full Vi compatibility.\n"
2386"2. Running Vim with some enhancements is useful when you want some of\n"
2387" the nice Vim features, but have a slow computer and want to keep it\n"
2388" really fast.\n"
2389"3. Syntax highlighting shows many files in color. Not only does this look\n"
2390" nice, it also makes it easier to spot errors and you can work faster.\n"
2391" The other features include editing compressed files.\n"
2392,
2393"Windows key mapping\n"
2394"-------------------\n"
2395"(this choice is only available when creating a _vimrc file)\n"
2396"Under MS-Windows the CTRL-C key copies text to the clipboard and CTRL-V\n"
2397"pastes text from the clipboard. There are a few more keys like these.\n"
2398"Unfortunately, in Vim these keys normally have another meaning.\n"
2399"1. Choose to have the keys like they normally are in Vim (useful if you\n"
2400" also use Vim on other systems).\n"
2401"2. Choose to have the keys work like they are used on MS-Windows (useful\n"
2402" if you mostly work on MS-Windows).\n"
2403,
2404"Mouse use\n"
2405"---------\n"
2406"(this choice is only available when creating a _vimrc file)\n"
2407"The right mouse button can be used in two ways:\n"
2408"1. The Unix way is to extend an existing selection. The popup menu is\n"
2409" not available.\n"
2410"2. The MS-Windows way is to show a popup menu, which allows you to\n"
2411" copy/paste text, undo/redo, etc. Extending the selection can still be\n"
2412" done by keeping SHIFT pressed while using the left mouse button\n"
2413,
2414"Edit-with-Vim context menu entry\n"
2415"--------------------------------\n"
2416"(this choice is only available when gvim.exe and gvimext.dll are present)\n"
2417"You can associate different file types with Vim, so that you can (double)\n"
2418"click on a file to edit it with Vim. This means you have to individually\n"
2419"select each file type.\n"
2420"An alternative is the option offered here: Install an \"Edit with Vim\"\n"
2421"entry in the popup menu for the right mouse button. This means you can\n"
2422"edit any file with Vim.\n"
2423,
2424"\"Open With...\" context menu entry\n"
2425"--------------------------------\n"
2426"(this choice is only available when gvim.exe is present)\n"
2427"This option adds Vim to the \"Open With...\" entry in the popup menu for\n"
2428"the right mouse button. This also makes it possible to edit HTML files\n"
2429"directly from Internet Explorer.\n"
2430,
2431"Add Vim to the Start menu\n"
2432"-------------------------\n"
2433"In Windows 95 and later, Vim can be added to the Start menu. This will\n"
2434"create a submenu with an entry for vim, gvim, evim, vimdiff, etc..\n"
2435,
2436"Icons on the desktop\n"
2437"--------------------\n"
2438"(these choices are only available when installing gvim)\n"
2439"In Windows 95 and later, shortcuts (icons) can be created on the Desktop.\n"
2440,
2441"Create plugin directories\n"
2442"-------------------------\n"
2443"Plugin directories allow extending Vim by dropping a file into a directory.\n"
2444"This choice allows creating them in $HOME (if you have a home directory) or\n"
2445"$VIM (used for everybody on the system).\n"
2446,
2447NULL
2448 };
2449 int i;
2450 int c;
2451
2452 rewind(stdin);
2453 printf("\n");
2454 for (i = 0; items[i] != NULL; ++i)
2455 {
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02002456 puts(items[i]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002457 printf("Hit Enter to continue, b (back) or q (quit help): ");
2458 c = getchar();
2459 rewind(stdin);
2460 if (c == 'b' || c == 'B')
2461 {
2462 if (i == 0)
2463 --i;
2464 else
2465 i -= 2;
2466 }
2467 if (c == 'q' || c == 'Q')
2468 break;
2469 printf("\n");
2470 }
2471}
2472
2473/*
2474 * Install the choices.
2475 */
2476 static void
2477install(void)
2478{
2479 int i;
2480
2481 /* Install the selected choices. */
2482 for (i = 0; i < choice_count; ++i)
2483 if (choices[i].installfunc != NULL && choices[i].active)
2484 (choices[i].installfunc)(i);
2485
2486 /* Add some entries to the registry, if needed. */
2487 if (install_popup
2488 || install_openwith
2489 || (need_uninstall_entry && interactive)
2490 || !interactive)
2491 install_registry();
2492
Bram Moolenaar071d4272004-06-13 20:20:40 +00002493 /* Register gvim with OLE. */
2494 if (has_gvim)
2495 install_OLE_register();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002496}
2497
2498/*
2499 * request_choice
2500 */
2501 static void
2502request_choice(void)
2503{
2504 int i;
2505
2506 printf("\n\nInstall will do for you:\n");
2507 for (i = 0; i < choice_count; ++i)
2508 if (choices[i].active)
2509 printf("%2d %s\n", i + 1, choices[i].text);
2510 printf("To change an item, enter its number\n\n");
2511 printf("Enter item number, h (help), d (do it) or q (quit): ");
2512}
2513
2514 int
2515main(int argc, char **argv)
2516{
2517 int i;
2518 char buf[BUFSIZE];
2519
2520 /*
2521 * Run interactively if there are no command line arguments.
2522 */
2523 if (argc > 1)
2524 interactive = 0;
2525 else
2526 interactive = 1;
2527
2528 /* Initialize this program. */
2529 do_inits(argv);
2530
Bram Moolenaar071d4272004-06-13 20:20:40 +00002531 if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
2532 {
2533 /* Only check for already installed Vims. Used by NSIS installer. */
Bram Moolenaar442b4222010-05-24 21:34:22 +02002534 i = uninstall_check(1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002535
2536 /* Find the value of $VIM, because NSIS isn't able to do this by
2537 * itself. */
2538 get_vim_env();
2539
2540 /* When nothing found exit quietly. If something found wait for
Bram Moolenaarb230bd52010-05-25 21:02:00 +02002541 * a little while, so that the user can read the messages. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542 if (i)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002543 sleep(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002544 exit(0);
2545 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002546
2547 printf("This program sets up the installation of Vim "
2548 VIM_VERSION_MEDIUM "\n\n");
2549
2550 /* Check if the user unpacked the archives properly. */
2551 check_unpack();
2552
Bram Moolenaar071d4272004-06-13 20:20:40 +00002553 /* Check for already installed Vims. */
2554 if (interactive)
Bram Moolenaar442b4222010-05-24 21:34:22 +02002555 uninstall_check(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002556
2557 /* Find out information about the system. */
2558 inspect_system();
2559
2560 if (interactive)
2561 {
2562 /* Setup all the choices. */
2563 setup_choices();
2564
2565 /* Let the user change choices and finally install (or quit). */
2566 for (;;)
2567 {
2568 request_choice();
2569 rewind(stdin);
2570 if (scanf("%99s", buf) == 1)
2571 {
2572 if (isdigit(buf[0]))
2573 {
2574 /* Change a choice. */
2575 i = atoi(buf);
2576 if (i > 0 && i <= choice_count && choices[i - 1].active)
2577 (choices[i - 1].changefunc)(i - 1);
2578 else
2579 printf("\nIllegal choice\n");
2580 }
2581 else if (buf[0] == 'h' || buf[0] == 'H')
2582 {
2583 /* Help */
2584 show_help();
2585 }
2586 else if (buf[0] == 'd' || buf[0] == 'D')
2587 {
2588 /* Install! */
2589 install();
2590 printf("\nThat finishes the installation. Happy Vimming!\n");
2591 break;
2592 }
2593 else if (buf[0] == 'q' || buf[0] == 'Q')
2594 {
2595 /* Quit */
2596 printf("\nExiting without anything done\n");
2597 break;
2598 }
2599 else
2600 printf("\nIllegal choice\n");
2601 }
2602 }
2603 printf("\n");
Bram Moolenaar442b4222010-05-24 21:34:22 +02002604 myexit(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002605 }
2606 else
2607 {
2608 /*
2609 * Run non-interactive - setup according to the command line switches
2610 */
2611 command_line_setup_choices(argc, argv);
2612 install();
Bram Moolenaar442b4222010-05-24 21:34:22 +02002613
2614 /* Avoid that the user has to hit Enter, just wait a little bit to
2615 * allow reading the messages. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002616 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002617 }
2618
Bram Moolenaar071d4272004-06-13 20:20:40 +00002619 return 0;
2620}