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