blob: 05398be37d2218594de4fe639848025d1e894ce3 [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
22/* Macro to do an error check I was typing over and over */
23#define CHECK_REG_ERROR(code) if (code != ERROR_SUCCESS) { printf("%ld error number: %ld\n", (long)__LINE__, (long)code); return 1; }
24
25int has_vim = 0; /* installable vim.exe exists */
26int has_gvim = 0; /* installable gvim.exe exists */
27
28char oldvimrc[BUFSIZE]; /* name of existing vimrc file */
29char vimrc[BUFSIZE]; /* name of vimrc file to create */
30
31char *default_bat_dir = NULL; /* when not NULL, use this as the default
32 directory to write .bat files in */
33char *default_vim_dir = NULL; /* when not NULL, use this as the default
34 install dir for NSIS */
Bram Moolenaar071d4272004-06-13 20:20:40 +000035
36/*
37 * Structure used for each choice the user can make.
38 */
39struct choice
40{
41 int active; /* non-zero when choice is active */
42 char *text; /* text displayed for this choice */
43 void (*changefunc)(int idx); /* function to change this choice */
44 int arg; /* argument for function */
45 void (*installfunc)(int idx); /* function to install this choice */
46};
47
48struct choice choices[30]; /* choices the user can make */
49int choice_count = 0; /* number of choices available */
50
51#define TABLE_SIZE(s) (int)(sizeof(s) / sizeof(*s))
52
53enum
54{
55 compat_vi = 1,
56 compat_some_enhancements,
57 compat_all_enhancements
58};
59char *(compat_choices[]) =
60{
61 "\nChoose the default way to run Vim:",
62 "Vi compatible",
Bram Moolenaarfff2bee2010-05-15 13:56:02 +020063 "with some Vim enhancements",
Bram Moolenaar071d4272004-06-13 20:20:40 +000064 "with syntax highlighting and other features switched on",
65};
66int compat_choice = (int)compat_all_enhancements;
67char *compat_text = "- run Vim %s";
68
69enum
70{
71 remap_no = 1,
72 remap_win
73};
74char *(remap_choices[]) =
75{
76 "\nChoose:",
77 "Do not remap keys for Windows behavior",
78 "Remap a few keys for Windows behavior (<C-V>, <C-C>, etc)",
79};
80int remap_choice = (int)remap_win;
81char *remap_text = "- %s";
82
83enum
84{
85 mouse_xterm = 1,
86 mouse_mswin
87};
88char *(mouse_choices[]) =
89{
90 "\nChoose the way how Vim uses the mouse:",
91 "right button extends selection (the Unix way)",
92 "right button has a popup menu (the Windows way)",
93};
94int mouse_choice = (int)mouse_mswin;
95char *mouse_text = "- The mouse %s";
96
97enum
98{
99 vimfiles_dir_none = 1,
100 vimfiles_dir_vim,
101 vimfiles_dir_home
102};
103static char *(vimfiles_dir_choices[]) =
104{
105 "\nCreate plugin directories:",
106 "No",
107 "In the VIM directory",
108 "In your HOME directory",
109};
110static int vimfiles_dir_choice;
111
112/* non-zero when selected to install the popup menu entry. */
113static int install_popup = 0;
114
115/* non-zero when selected to install the "Open with" entry. */
116static int install_openwith = 0;
117
118/* non-zero when need to add an uninstall entry in the registry */
119static int need_uninstall_entry = 0;
120
121/*
122 * Definitions of the directory name (under $VIM) of the vimfiles directory
123 * and its subdirectories:
124 */
125static char *(vimfiles_subdirs[]) =
126{
127 "colors",
128 "compiler",
129 "doc",
130 "ftdetect",
131 "ftplugin",
132 "indent",
133 "keymap",
134 "plugin",
135 "syntax",
136};
137
138/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139 * Obtain a choice from a table.
140 * First entry is a question, others are choices.
141 */
142 static int
143get_choice(char **table, int entries)
144{
145 int answer;
146 int idx;
147 char dummy[100];
148
149 do
150 {
151 for (idx = 0; idx < entries; ++idx)
152 {
153 if (idx)
154 printf("%2d ", idx);
155 printf(table[idx]);
156 printf("\n");
157 }
158 printf("Choice: ");
159 if (scanf("%d", &answer) != 1)
160 {
161 scanf("%99s", dummy);
162 answer = 0;
163 }
164 }
165 while (answer < 1 || answer >= entries);
166
167 return answer;
168}
169
170/*
171 * Check if the user unpacked the archives properly.
172 * Sets "runtimeidx".
173 */
174 static void
175check_unpack(void)
176{
177 char buf[BUFSIZE];
178 FILE *fd;
179 struct stat st;
180
181 /* check for presence of the correct version number in installdir[] */
182 runtimeidx = strlen(installdir) - strlen(VIM_VERSION_NODOT);
183 if (runtimeidx <= 0
184 || stricmp(installdir + runtimeidx, VIM_VERSION_NODOT) != 0
185 || (installdir[runtimeidx - 1] != '/'
186 && installdir[runtimeidx - 1] != '\\'))
187 {
188 printf("ERROR: Install program not in directory \"%s\"\n",
189 VIM_VERSION_NODOT);
190 printf("This program can only work when it is located in its original directory\n");
191 myexit(1);
192 }
193
194 /* check if filetype.vim is present, which means the runtime archive has
195 * been unpacked */
196 sprintf(buf, "%s\\filetype.vim", installdir);
197 if (stat(buf, &st) < 0)
198 {
199 printf("ERROR: Cannot find filetype.vim in \"%s\"\n", installdir);
200 printf("It looks like you did not unpack the runtime archive.\n");
201 printf("You must unpack the runtime archive \"vim%srt.zip\" before installing.\n",
202 VIM_VERSION_NODOT + 3);
203 myexit(1);
204 }
205
206 /* Check if vim.exe or gvim.exe is in the current directory. */
207 if ((fd = fopen("gvim.exe", "r")) != NULL)
208 {
209 fclose(fd);
210 has_gvim = 1;
211 }
212 if ((fd = fopen("vim.exe", "r")) != NULL)
213 {
214 fclose(fd);
215 has_vim = 1;
216 }
217 if (!has_gvim && !has_vim)
218 {
219 printf("ERROR: Cannot find any Vim executables in \"%s\"\n\n",
220 installdir);
221 myexit(1);
222 }
223}
224
225/*
226 * Compare paths "p[plen]" to "q[qlen]". Return 0 if they match.
227 * Ignores case and differences between '/' and '\'.
228 * "plen" and "qlen" can be negative, strlen() is used then.
229 */
230 static int
231pathcmp(char *p, int plen, char *q, int qlen)
232{
233 int i;
234
235 if (plen < 0)
236 plen = strlen(p);
237 if (qlen < 0)
238 qlen = strlen(q);
239 for (i = 0; ; ++i)
240 {
241 /* End of "p": check if "q" also ends or just has a slash. */
242 if (i == plen)
243 {
244 if (i == qlen) /* match */
245 return 0;
246 if (i == qlen - 1 && (q[i] == '\\' || q[i] == '/'))
247 return 0; /* match with trailing slash */
248 return 1; /* no match */
249 }
250
251 /* End of "q": check if "p" also ends or just has a slash. */
252 if (i == qlen)
253 {
254 if (i == plen) /* match */
255 return 0;
256 if (i == plen - 1 && (p[i] == '\\' || p[i] == '/'))
257 return 0; /* match with trailing slash */
258 return 1; /* no match */
259 }
260
261 if (!(mytoupper(p[i]) == mytoupper(q[i])
262 || ((p[i] == '/' || p[i] == '\\')
263 && (q[i] == '/' || q[i] == '\\'))))
264 return 1; /* no match */
265 }
266 /*NOTREACHED*/
267}
268
269/*
270 * If the executable "**destination" is in the install directory, find another
271 * one in $PATH.
272 * On input "**destination" is the path of an executable in allocated memory
273 * (or NULL).
274 * "*destination" is set to NULL or the location of the file.
275 */
276 static void
277findoldfile(char **destination)
278{
279 char *bp = *destination;
280 size_t indir_l = strlen(installdir);
281 char *cp = bp + indir_l;
282 char *tmpname;
283 char *farname;
284
285 /*
286 * No action needed if exe not found or not in this directory.
287 */
288 if (bp == NULL
289 || strnicmp(bp, installdir, indir_l) != 0
290 || strchr("/\\", *cp++) == NULL
291 || strchr(cp, '\\') != NULL
292 || strchr(cp, '/') != NULL)
293 return;
294
295 tmpname = alloc((int)strlen(cp) + 1);
296 strcpy(tmpname, cp);
297 tmpname[strlen(tmpname) - 1] = 'x'; /* .exe -> .exx */
298
299 if (access(tmpname, 0) == 0)
300 {
301 printf("\nERROR: %s and %s clash. Remove or rename %s.\n",
302 tmpname, cp, tmpname);
303 myexit(1);
304 }
305
306 if (rename(cp, tmpname) != 0)
307 {
308 printf("\nERROR: failed to rename %s to %s: %s\n",
309 cp, tmpname, strerror(0));
310 myexit(1);
311 }
312
313 farname = searchpath_save(cp);
314
315 if (rename(tmpname, cp) != 0)
316 {
317 printf("\nERROR: failed to rename %s back to %s: %s\n",
318 tmpname, cp, strerror(0));
319 myexit(1);
320 }
321
322 free(*destination);
323 free(tmpname);
324 *destination = farname;
325}
326
327/*
328 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
329 * When "check_bat_only" is TRUE, only find "default_bat_dir".
330 */
331 static void
332find_bat_exe(int check_bat_only)
333{
334 int i;
335
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000336 /* avoid looking in the "installdir" by chdir to system root */
337 mch_chdir(sysdrive);
338 mch_chdir("\\");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000339
340 for (i = 1; i < TARGET_COUNT; ++i)
341 {
342 targets[i].oldbat = searchpath_save(targets[i].batname);
343 if (!check_bat_only)
344 targets[i].oldexe = searchpath_save(targets[i].exename);
345
346 if (default_bat_dir == NULL && targets[i].oldbat != NULL)
347 {
348 default_bat_dir = alloc(strlen(targets[i].oldbat) + 1);
349 strcpy(default_bat_dir, targets[i].oldbat);
350 remove_tail(default_bat_dir);
351 }
352 if (check_bat_only && targets[i].oldbat != NULL)
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000353 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000354 free(targets[i].oldbat);
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000355 targets[i].oldbat = NULL;
356 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357 }
358
359 mch_chdir(installdir);
360}
361
362#ifdef WIN3264
363/*
364 * Get the value of $VIMRUNTIME or $VIM and write it in $TEMP/vimini.ini, so
365 * that NSIS can read it.
366 * When not set, use the directory of a previously installed Vim.
367 */
368 static void
369get_vim_env(void)
370{
371 char *vim;
372 char buf[BUFSIZE];
373 FILE *fd;
374 char fname[BUFSIZE];
375
376 /* First get $VIMRUNTIME. If it's set, remove the tail. */
377 vim = getenv("VIMRUNTIME");
Bram Moolenaar181ace22013-02-13 14:36:44 +0100378 if (vim != NULL && *vim != 0 && strlen(vim) < BUFSIZE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000379 {
380 strcpy(buf, vim);
381 remove_tail(buf);
382 vim = buf;
383 }
384 else
385 {
386 vim = getenv("VIM");
387 if (vim == NULL || *vim == 0)
388 {
389 /* Use the directory from an old uninstall entry. */
390 if (default_vim_dir != NULL)
391 vim = default_vim_dir;
392 else
393 /* Let NSIS know there is no default, it should use
Bram Moolenaarb8017e72007-05-10 18:59:07 +0000394 * $PROGRAMFILES. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 vim = "";
396 }
397 }
398
399 /* NSIS also uses GetTempPath(), thus we should get the same directory
400 * name as where NSIS will look for vimini.ini. */
401 GetTempPath(BUFSIZE, fname);
402 add_pathsep(fname);
403 strcat(fname, "vimini.ini");
404
405 fd = fopen(fname, "w");
406 if (fd != NULL)
407 {
408 /* Make it look like an .ini file, so that NSIS can read it with a
409 * ReadINIStr command. */
410 fprintf(fd, "[vimini]\n");
411 fprintf(fd, "dir=\"%s\"\n", vim);
412 fclose(fd);
413 }
414 else
415 {
416 printf("Failed to open %s\n", fname);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200417 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000418 }
419}
420
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200421static int num_windows;
422
423/*
424 * Callback used for EnumWindows():
425 * Count the window if the title looks like it is for the uninstaller.
426 */
427/*ARGSUSED*/
428 static BOOL CALLBACK
429window_cb(HWND hwnd, LPARAM lparam)
430{
431 char title[256];
432
433 title[0] = 0;
434 GetWindowText(hwnd, title, 256);
435 if (strstr(title, "Vim ") != NULL && strstr(title, "Uninstall:") != NULL)
436 ++num_windows;
437 return TRUE;
438}
439
Bram Moolenaar071d4272004-06-13 20:20:40 +0000440/*
441 * Check for already installed Vims.
442 * Return non-zero when found one.
443 */
444 static int
Bram Moolenaar442b4222010-05-24 21:34:22 +0200445uninstall_check(int skip_question)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446{
447 HKEY key_handle;
448 HKEY uninstall_key_handle;
449 char *uninstall_key = "software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
450 char subkey_name_buff[BUFSIZE];
451 char temp_string_buffer[BUFSIZE];
452 DWORD local_bufsize = BUFSIZE;
453 FILETIME temp_pfiletime;
454 DWORD key_index;
455 char input;
456 long code;
457 DWORD value_type;
458 DWORD orig_num_keys;
459 DWORD new_num_keys;
460 int foundone = 0;
461
Bram Moolenaar760d14a2010-07-31 22:03:44 +0200462 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0,
463 KEY_WOW64_64KEY | KEY_READ, &key_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000464 CHECK_REG_ERROR(code);
465
466 for (key_index = 0;
467 RegEnumKeyEx(key_handle, key_index, subkey_name_buff, &local_bufsize,
468 NULL, NULL, NULL, &temp_pfiletime) != ERROR_NO_MORE_ITEMS;
469 key_index++)
470 {
471 local_bufsize = BUFSIZE;
472 if (strncmp("Vim", subkey_name_buff, 3) == 0)
473 {
474 /* Open the key named Vim* */
Bram Moolenaar760d14a2010-07-31 22:03:44 +0200475 code = RegOpenKeyEx(key_handle, subkey_name_buff, 0,
476 KEY_WOW64_64KEY | KEY_READ, &uninstall_key_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000477 CHECK_REG_ERROR(code);
478
479 /* get the DisplayName out of it to show the user */
480 code = RegQueryValueEx(uninstall_key_handle, "displayname", 0,
481 &value_type, (LPBYTE)temp_string_buffer,
482 &local_bufsize);
483 local_bufsize = BUFSIZE;
484 CHECK_REG_ERROR(code);
485
486 foundone = 1;
487 printf("\n*********************************************************\n");
488 printf("Vim Install found what looks like an existing Vim version.\n");
489 printf("The name of the entry is:\n");
490 printf("\n \"%s\"\n\n", temp_string_buffer);
491
492 printf("Installing the new version will disable part of the existing version.\n");
493 printf("(The batch files used in a console and the \"Edit with Vim\" entry in\n");
494 printf("the popup menu will use the new version)\n");
495
Bram Moolenaar442b4222010-05-24 21:34:22 +0200496 if (skip_question)
497 printf("\nRunning uninstall program for \"%s\"\n", temp_string_buffer);
498 else
499 printf("\nDo you want to uninstall \"%s\" now?\n(y)es/(n)o) ", temp_string_buffer);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000500 fflush(stdout);
501
502 /* get the UninstallString */
503 code = RegQueryValueEx(uninstall_key_handle, "uninstallstring", 0,
504 &value_type, (LPBYTE)temp_string_buffer, &local_bufsize);
505 local_bufsize = BUFSIZE;
506 CHECK_REG_ERROR(code);
507
508 /* Remember the directory, it is used as the default for NSIS. */
509 default_vim_dir = alloc(strlen(temp_string_buffer) + 1);
510 strcpy(default_vim_dir, temp_string_buffer);
511 remove_tail(default_vim_dir);
512 remove_tail(default_vim_dir);
513
514 input = 'n';
515 do
516 {
517 if (input != 'n')
518 printf("%c is an invalid reply. Please enter either 'y' or 'n'\n", input);
519
Bram Moolenaar442b4222010-05-24 21:34:22 +0200520 if (skip_question)
521 input = 'y';
522 else
523 {
524 rewind(stdin);
525 scanf("%c", &input);
526 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 switch (input)
528 {
529 case 'y':
530 case 'Y':
531 /* save the number of uninstall keys so we can know if
532 * it changed */
533 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
534 &orig_num_keys, NULL, NULL, NULL,
535 NULL, NULL, NULL, NULL);
536
Bram Moolenaar442b4222010-05-24 21:34:22 +0200537 /* Find existing .bat files before deleting them. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000538 find_bat_exe(TRUE);
539
540 /* Execute the uninstall program. Put it in double
541 * quotes if there is an embedded space. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000542 {
543 char buf[BUFSIZE];
544
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200545 if (strchr(temp_string_buffer, ' ') != NULL)
546 sprintf(buf, "\"%s\"", temp_string_buffer);
547 else
548 strcpy(buf, temp_string_buffer);
549 run_command(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000550 }
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200551
552 /* Count the number of windows with a title that match
553 * the installer, so that we can check when it's done.
554 * The uninstaller copies itself, executes the copy
555 * and exits, thus we can't wait for the process to
556 * finish. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200557 sleep(1); /* wait for uninstaller to start up */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200558 num_windows = 0;
559 EnumWindows(window_cb, 0);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200560 sleep(1); /* wait for windows to be counted */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200561 if (num_windows == 0)
562 {
563 /* Did not find the uninstaller, ask user to press
564 * Enter when done. Just in case. */
565 printf("Press Enter when the uninstaller is finished\n");
566 rewind(stdin);
567 (void)getchar();
568 }
569 else
570 {
571 printf("Waiting for the uninstaller to finish (press CTRL-C to abort).");
572 do
573 {
574 printf(".");
575 fflush(stdout);
576 num_windows = 0;
577 EnumWindows(window_cb, 0);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200578 sleep(1); /* wait for windows to be counted */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200579 } while (num_windows > 0);
580 }
581 printf("\nDone!\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000582
Bram Moolenaarfff2bee2010-05-15 13:56:02 +0200583 /* Check if an uninstall reg key was deleted.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000584 * if it was, we want to decrement key_index.
585 * if we don't do this, we will skip the key
586 * immediately after any key that we delete. */
587 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
588 &new_num_keys, NULL, NULL, NULL,
589 NULL, NULL, NULL, NULL);
590 if (new_num_keys < orig_num_keys)
591 key_index--;
592
593 input = 'y';
594 break;
595
596 case 'n':
597 case 'N':
598 /* Do not uninstall */
599 input = 'n';
600 break;
601
602 default: /* just drop through and redo the loop */
603 break;
604 }
605
606 } while (input != 'n' && input != 'y');
607
608 RegCloseKey(uninstall_key_handle);
609 }
610 }
611 RegCloseKey(key_handle);
612
613 return foundone;
614}
615#endif
616
617/*
618 * Find out information about the system.
619 */
620 static void
621inspect_system(void)
622{
623 char *p;
624 char buf[BUFSIZE];
625 FILE *fd;
626 int i;
627 int foundone;
628
629 /* This may take a little while, let the user know what we're doing. */
630 printf("Inspecting system...\n");
631
632 /*
633 * If $VIM is set, check that it's pointing to our directory.
634 */
635 p = getenv("VIM");
636 if (p != NULL && pathcmp(p, -1, installdir, runtimeidx - 1) != 0)
637 {
638 printf("------------------------------------------------------\n");
639 printf("$VIM is set to \"%s\".\n", p);
640 printf("This is different from where this version of Vim is:\n");
641 strcpy(buf, installdir);
642 *(buf + runtimeidx - 1) = NUL;
643 printf("\"%s\"\n", buf);
644 printf("You must adjust or remove the setting of $VIM,\n");
645 if (interactive)
646 {
647 printf("to be able to use this install program.\n");
648 myexit(1);
649 }
650 printf("otherwise Vim WILL NOT WORK properly!\n");
651 printf("------------------------------------------------------\n");
652 }
653
654 /*
655 * If $VIMRUNTIME is set, check that it's pointing to our runtime directory.
656 */
657 p = getenv("VIMRUNTIME");
658 if (p != NULL && pathcmp(p, -1, installdir, -1) != 0)
659 {
660 printf("------------------------------------------------------\n");
661 printf("$VIMRUNTIME is set to \"%s\".\n", p);
662 printf("This is different from where this version of Vim is:\n");
663 printf("\"%s\"\n", installdir);
664 printf("You must adjust or remove the setting of $VIMRUNTIME,\n");
665 if (interactive)
666 {
667 printf("to be able to use this install program.\n");
668 myexit(1);
669 }
670 printf("otherwise Vim WILL NOT WORK properly!\n");
671 printf("------------------------------------------------------\n");
672 }
673
674 /*
675 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
676 */
677 find_bat_exe(FALSE);
678
679 /*
680 * A .exe in the install directory may be found anyway on Windows 2000.
681 * Check for this situation and find another executable if necessary.
682 * w.briscoe@ponl.com 2001-01-20
683 */
684 foundone = 0;
685 for (i = 1; i < TARGET_COUNT; ++i)
686 {
687 findoldfile(&(targets[i].oldexe));
688 if (targets[i].oldexe != NULL)
689 foundone = 1;
690 }
691
692 if (foundone)
693 {
694 printf("Warning: Found Vim executable(s) in your $PATH:\n");
695 for (i = 1; i < TARGET_COUNT; ++i)
696 if (targets[i].oldexe != NULL)
697 printf("%s\n", targets[i].oldexe);
698 printf("It will be used instead of the version you are installing.\n");
699 printf("Please delete or rename it, or adjust your $PATH setting.\n");
700 }
701
702 /*
703 * Check if there is an existing ../_vimrc or ../.vimrc file.
704 */
705 strcpy(oldvimrc, installdir);
706 strcpy(oldvimrc + runtimeidx, "_vimrc");
707 if ((fd = fopen(oldvimrc, "r")) == NULL)
708 {
709 strcpy(oldvimrc + runtimeidx, "vimrc~1"); /* short version of .vimrc */
710 if ((fd = fopen(oldvimrc, "r")) == NULL)
711 {
712 strcpy(oldvimrc + runtimeidx, ".vimrc");
713 fd = fopen(oldvimrc, "r");
714 }
715 }
716 if (fd != NULL)
717 fclose(fd);
718 else
719 *oldvimrc = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000720}
721
722/*
723 * Add a dummy choice to avoid that the numbering changes depending on items
724 * in the environment. The user may type a number he remembered without
725 * looking.
726 */
727 static void
728add_dummy_choice(void)
729{
730 choices[choice_count].installfunc = NULL;
731 choices[choice_count].active = 0;
732 choices[choice_count].changefunc = NULL;
733 choices[choice_count].installfunc = NULL;
734 ++choice_count;
735}
736
737/***********************************************
738 * stuff for creating the batch files.
739 */
740
741/*
742 * Install the vim.bat, gvim.bat, etc. files.
743 */
744 static void
745install_bat_choice(int idx)
746{
747 char *batpath = targets[choices[idx].arg].batpath;
748 char *oldname = targets[choices[idx].arg].oldbat;
749 char *exename = targets[choices[idx].arg].exenamearg;
750 char *vimarg = targets[choices[idx].arg].exearg;
751 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000752
753 if (*batpath != NUL)
754 {
755 fd = fopen(batpath, "w");
756 if (fd == NULL)
757 printf("\nERROR: Cannot open \"%s\" for writing.\n", batpath);
758 else
759 {
760 need_uninstall_entry = 1;
761
762 fprintf(fd, "@echo off\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000763 fprintf(fd, "rem -- Run Vim --\n");
764 fprintf(fd, "\n");
Bram Moolenaare609ad52016-03-28 23:05:48 +0200765 fprintf(fd, "setlocal\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000766
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000767 /* Don't use double quotes for the "set" argument, also when it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768 * contains a space. The quotes would be included in the value
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000769 * for MSDOS and NT.
770 * The order of preference is:
771 * 1. $VIMRUNTIME/vim.exe (user preference)
772 * 2. $VIM/vim70/vim.exe (hard coded version)
773 * 3. installdir/vim.exe (hard coded install directory)
774 */
775 fprintf(fd, "set VIM_EXE_DIR=%s\n", installdir);
776 fprintf(fd, "if exist \"%%VIM%%\\%s\\%s\" set VIM_EXE_DIR=%%VIM%%\\%s\n",
777 VIM_VERSION_NODOT, exename, VIM_VERSION_NODOT);
778 fprintf(fd, "if exist \"%%VIMRUNTIME%%\\%s\" set VIM_EXE_DIR=%%VIMRUNTIME%%\n", exename);
779 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780
781 /* Give an error message when the executable could not be found. */
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000782 fprintf(fd, "if exist \"%%VIM_EXE_DIR%%\\%s\" goto havevim\n",
783 exename);
784 fprintf(fd, "echo \"%%VIM_EXE_DIR%%\\%s\" not found\n", exename);
785 fprintf(fd, "goto eof\n");
786 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787 fprintf(fd, ":havevim\n");
788
789 fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
790 fprintf(fd, "set VIMARGS=\n");
791 if (*exename == 'g')
792 fprintf(fd, "set VIMNOFORK=\n");
793 fprintf(fd, ":loopstart\n");
794 fprintf(fd, "if .%%1==. goto loopend\n");
795 if (*exename == 'g')
796 {
Bram Moolenaare609ad52016-03-28 23:05:48 +0200797 fprintf(fd, "if NOT .%%1==.--nofork goto noforklongarg\n");
798 fprintf(fd, "set VIMNOFORK=1\n");
799 fprintf(fd, ":noforklongarg\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800 fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
801 fprintf(fd, "set VIMNOFORK=1\n");
802 fprintf(fd, ":noforkarg\n");
803 }
804 fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
805 fprintf(fd, "shift\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000806 fprintf(fd, "goto loopstart\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000807 fprintf(fd, ":loopend\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000808 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000810 fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n");
811 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812
813 /* For gvim.exe use "start" to avoid that the console window stays
814 * open. */
815 if (*exename == 'g')
816 {
817 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
818 fprintf(fd, "start ");
819 }
820
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000821 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
822 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
823 exename, vimarg);
824 fprintf(fd, "goto eof\n");
825 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826
827 if (*exename == 'g')
828 {
829 fprintf(fd, ":nofork\n");
830 fprintf(fd, "start /w ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000831 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
832 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
833 exename, vimarg);
834 fprintf(fd, "goto eof\n");
835 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 }
837
838 fprintf(fd, ":ntaction\n");
839 fprintf(fd, "rem for WinNT we can use %%*\n");
840
841 /* For gvim.exe use "start /b" to avoid that the console window
842 * stays open. */
843 if (*exename == 'g')
844 {
845 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
846 fprintf(fd, "start \"dummy\" /b ");
847 }
848
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000849 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
850 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n", exename, vimarg);
851 fprintf(fd, "goto eof\n");
852 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853
854 if (*exename == 'g')
855 {
856 fprintf(fd, ":noforknt\n");
857 fprintf(fd, "start \"dummy\" /b /wait ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000858 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
859 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n",
860 exename, vimarg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 }
862
863 fprintf(fd, "\n:eof\n");
864 fprintf(fd, "set VIMARGS=\n");
865 if (*exename == 'g')
866 fprintf(fd, "set VIMNOFORK=\n");
867
868 fclose(fd);
869 printf("%s has been %s\n", batpath,
870 oldname == NULL ? "created" : "overwritten");
871 }
872 }
873}
874
875/*
876 * Make the text string for choice "idx".
877 * The format "fmt" is must have one %s item, which "arg" is used for.
878 */
879 static void
880alloc_text(int idx, char *fmt, char *arg)
881{
882 if (choices[idx].text != NULL)
883 free(choices[idx].text);
884
885 choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
886 sprintf(choices[idx].text, fmt, arg);
887}
888
889/*
890 * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
891 */
892 static void
893toggle_bat_choice(int idx)
894{
895 char *batname = targets[choices[idx].arg].batpath;
896 char *oldname = targets[choices[idx].arg].oldbat;
897
898 if (*batname == NUL)
899 {
900 alloc_text(idx, " Overwrite %s", oldname);
901 strcpy(batname, oldname);
902 }
903 else
904 {
905 alloc_text(idx, " Do NOT overwrite %s", oldname);
906 *batname = NUL;
907 }
908}
909
910/*
911 * Do some work for a batch file entry: Append the batch file name to the path
912 * and set the text for the choice.
913 */
914 static void
915set_bat_text(int idx, char *batpath, char *name)
916{
917 strcat(batpath, name);
918
919 alloc_text(idx, " Create %s", batpath);
920}
921
922/*
923 * Select a directory to write the batch file line.
924 */
925 static void
926change_bat_choice(int idx)
927{
928 char *path;
929 char *batpath;
930 char *name;
931 int n;
932 char *s;
933 char *p;
934 int count;
935 char **names = NULL;
936 int i;
937 int target = choices[idx].arg;
938
939 name = targets[target].batname;
940 batpath = targets[target].batpath;
941
942 path = getenv("PATH");
943 if (path == NULL)
944 {
945 printf("\nERROR: The variable $PATH is not set\n");
946 return;
947 }
948
949 /*
950 * first round: count number of names in path;
951 * second round: save names to names[].
952 */
953 for (;;)
954 {
955 count = 1;
956 for (p = path; *p; )
957 {
958 s = strchr(p, ';');
959 if (s == NULL)
960 s = p + strlen(p);
961 if (names != NULL)
962 {
963 names[count] = alloc((int)(s - p) + 1);
964 strncpy(names[count], p, s - p);
965 names[count][s - p] = NUL;
966 }
967 ++count;
968 p = s;
969 if (*p != NUL)
970 ++p;
971 }
972 if (names != NULL)
973 break;
974 names = alloc((int)(count + 1) * sizeof(char *));
975 }
976 names[0] = alloc(50);
977 sprintf(names[0], "Select directory to create %s in:", name);
978 names[count] = alloc(50);
979 if (choices[idx].arg == 0)
980 sprintf(names[count], "Do not create any .bat file.");
981 else
982 sprintf(names[count], "Do not create a %s file.", name);
983 n = get_choice(names, count + 1);
984
985 if (n == count)
986 {
987 /* Selected last item, don't create bat file. */
988 *batpath = NUL;
989 if (choices[idx].arg != 0)
990 alloc_text(idx, " Do NOT create %s", name);
991 }
992 else
993 {
994 /* Selected one of the paths. For the first item only keep the path,
995 * for the others append the batch file name. */
996 strcpy(batpath, names[n]);
997 add_pathsep(batpath);
998 if (choices[idx].arg != 0)
999 set_bat_text(idx, batpath, name);
1000 }
1001
1002 for (i = 0; i <= count; ++i)
1003 free(names[i]);
1004 free(names);
1005}
1006
1007char *bat_text_yes = "Install .bat files to use Vim at the command line:";
1008char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
1009
1010 static void
1011change_main_bat_choice(int idx)
1012{
1013 int i;
1014
1015 /* let the user select a default directory or NONE */
1016 change_bat_choice(idx);
1017
1018 if (targets[0].batpath[0] != NUL)
1019 choices[idx].text = bat_text_yes;
1020 else
1021 choices[idx].text = bat_text_no;
1022
1023 /* update the individual batch file selections */
1024 for (i = 1; i < TARGET_COUNT; ++i)
1025 {
1026 /* Only make it active when the first item has a path and the vim.exe
1027 * or gvim.exe exists (there is a changefunc then). */
1028 if (targets[0].batpath[0] != NUL
1029 && choices[idx + i].changefunc != NULL)
1030 {
1031 choices[idx + i].active = 1;
1032 if (choices[idx + i].changefunc == change_bat_choice
1033 && targets[i].batpath[0] != NUL)
1034 {
1035 strcpy(targets[i].batpath, targets[0].batpath);
1036 set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
1037 }
1038 }
1039 else
1040 choices[idx + i].active = 0;
1041 }
1042}
1043
1044/*
1045 * Initialize a choice for creating a batch file.
1046 */
1047 static void
1048init_bat_choice(int target)
1049{
1050 char *batpath = targets[target].batpath;
1051 char *oldbat = targets[target].oldbat;
1052 char *p;
1053 int i;
1054
1055 choices[choice_count].arg = target;
1056 choices[choice_count].installfunc = install_bat_choice;
1057 choices[choice_count].active = 1;
1058 choices[choice_count].text = NULL; /* will be set below */
1059 if (oldbat != NULL)
1060 {
1061 /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
1062 choices[choice_count].changefunc = toggle_bat_choice;
1063 *batpath = NUL;
1064 toggle_bat_choice(choice_count);
1065 }
1066 else
1067 {
1068 if (default_bat_dir != NULL)
1069 /* Prefer using the same path as an existing .bat file. */
1070 strcpy(batpath, default_bat_dir);
1071 else
1072 {
1073 /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
1074 * $WINDIR by default, if it's empty the first item in $PATH. */
1075 p = getenv("WINDIR");
1076 if (p != NULL && *p != NUL)
1077 strcpy(batpath, p);
1078 else
1079 {
1080 p = getenv("PATH");
1081 if (p == NULL || *p == NUL) /* "cannot happen" */
1082 strcpy(batpath, "C:/Windows");
1083 else
1084 {
1085 i = 0;
1086 while (*p != NUL && *p != ';')
1087 batpath[i++] = *p++;
1088 batpath[i] = NUL;
1089 }
1090 }
1091 }
1092 add_pathsep(batpath);
1093 set_bat_text(choice_count, batpath, targets[target].batname);
1094
1095 choices[choice_count].changefunc = change_bat_choice;
1096 }
1097 ++choice_count;
1098}
1099
1100/*
1101 * Set up the choices for installing .bat files.
1102 * For these items "arg" is the index in targets[].
1103 */
1104 static void
1105init_bat_choices(void)
1106{
1107 int i;
1108
1109 /* The first item is used to switch installing batch files on/off and
1110 * setting the default path. */
1111 choices[choice_count].text = bat_text_yes;
1112 choices[choice_count].changefunc = change_main_bat_choice;
1113 choices[choice_count].installfunc = NULL;
1114 choices[choice_count].active = 1;
1115 choices[choice_count].arg = 0;
1116 ++choice_count;
1117
1118 /* Add items for each batch file target. Only used when not disabled by
1119 * the first item. When a .exe exists, don't offer to create a .bat. */
1120 for (i = 1; i < TARGET_COUNT; ++i)
1121 if (targets[i].oldexe == NULL
1122 && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
1123 init_bat_choice(i);
1124 else
1125 add_dummy_choice();
1126}
1127
1128/*
1129 * Install the vimrc file.
1130 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131 static void
1132install_vimrc(int idx)
1133{
1134 FILE *fd, *tfd;
1135 char *fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136
1137 /* If an old vimrc file exists, overwrite it.
1138 * Otherwise create a new one. */
1139 if (*oldvimrc != NUL)
1140 fname = oldvimrc;
1141 else
1142 fname = vimrc;
1143
1144 fd = fopen(fname, "w");
1145 if (fd == NULL)
1146 {
1147 printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
1148 return;
1149 }
1150 switch (compat_choice)
1151 {
1152 case compat_vi:
1153 fprintf(fd, "set compatible\n");
1154 break;
1155 case compat_some_enhancements:
Bram Moolenaarc73e4472016-07-29 18:33:38 +02001156 fprintf(fd, "source $VIMRUNTIME/defaults.vim\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001157 break;
1158 case compat_all_enhancements:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159 fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
1160 break;
1161 }
1162 switch (remap_choice)
1163 {
1164 case remap_no:
1165 break;
1166 case remap_win:
1167 fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
1168 break;
1169 }
1170 switch (mouse_choice)
1171 {
1172 case mouse_xterm:
1173 fprintf(fd, "behave xterm\n");
1174 break;
1175 case mouse_mswin:
1176 fprintf(fd, "behave mswin\n");
1177 break;
1178 }
1179 if ((tfd = fopen("diff.exe", "r")) != NULL)
1180 {
1181 /* Use the diff.exe that comes with the self-extracting gvim.exe. */
1182 fclose(tfd);
1183 fprintf(fd, "\n");
1184 fprintf(fd, "set diffexpr=MyDiff()\n");
1185 fprintf(fd, "function MyDiff()\n");
1186 fprintf(fd, " let opt = '-a --binary '\n");
1187 fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
1188 fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
1189 /* Use quotes only when needed, they may cause trouble. */
1190 fprintf(fd, " let arg1 = v:fname_in\n");
1191 fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
1192 fprintf(fd, " let arg2 = v:fname_new\n");
1193 fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
1194 fprintf(fd, " let arg3 = v:fname_out\n");
1195 fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001196
1197 /* If the path has a space: When using cmd.exe (Win NT/2000/XP) put
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001198 * quotes around the diff command and rely on the default value of
1199 * shellxquote to solve the quoting problem for the whole command.
1200 *
Bram Moolenaar33aec762006-01-22 23:30:12 +00001201 * Otherwise put a double quote just before the space and at the
1202 * end of the command. Putting quotes around the whole thing
1203 * doesn't work on Win 95/98/ME. This is mostly guessed! */
Bram Moolenaar33aec762006-01-22 23:30:12 +00001204 fprintf(fd, " if $VIMRUNTIME =~ ' '\n");
1205 fprintf(fd, " if &sh =~ '\\<cmd'\n");
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001206 fprintf(fd, " if empty(&shellxquote)\n");
1207 fprintf(fd, " let l:shxq_sav = ''\n");
1208 fprintf(fd, " set shellxquote&\n");
1209 fprintf(fd, " endif\n");
1210 fprintf(fd, " let cmd = '\"' . $VIMRUNTIME . '\\diff\"'\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001211 fprintf(fd, " else\n");
1212 fprintf(fd, " let cmd = substitute($VIMRUNTIME, ' ', '\" ', '') . '\\diff\"'\n");
1213 fprintf(fd, " endif\n");
1214 fprintf(fd, " else\n");
1215 fprintf(fd, " let cmd = $VIMRUNTIME . '\\diff'\n");
1216 fprintf(fd, " endif\n");
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001217 fprintf(fd, " silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n");
1218 fprintf(fd, " if exists('l:shxq_sav')\n");
1219 fprintf(fd, " let &shellxquote=l:shxq_sav\n");
1220 fprintf(fd, " endif\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001221 fprintf(fd, "endfunction\n");
1222 fprintf(fd, "\n");
1223 }
1224 fclose(fd);
1225 printf("%s has been written\n", fname);
1226}
1227
1228 static void
1229change_vimrc_choice(int idx)
1230{
1231 if (choices[idx].installfunc != NULL)
1232 {
1233 /* Switch to NOT change or create a vimrc file. */
1234 if (*oldvimrc != NUL)
1235 alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
1236 else
1237 alloc_text(idx, "Do NOT create startup file %s", vimrc);
1238 choices[idx].installfunc = NULL;
1239 choices[idx + 1].active = 0;
1240 choices[idx + 2].active = 0;
1241 choices[idx + 3].active = 0;
1242 }
1243 else
1244 {
1245 /* Switch to change or create a vimrc file. */
1246 if (*oldvimrc != NUL)
1247 alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
1248 else
1249 alloc_text(idx, "Create startup file %s with:", vimrc);
1250 choices[idx].installfunc = install_vimrc;
1251 choices[idx + 1].active = 1;
1252 choices[idx + 2].active = 1;
1253 choices[idx + 3].active = 1;
1254 }
1255}
1256
1257/*
1258 * Change the choice how to run Vim.
1259 */
1260 static void
1261change_run_choice(int idx)
1262{
1263 compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
1264 alloc_text(idx, compat_text, compat_choices[compat_choice]);
1265}
1266
1267/*
1268 * Change the choice if keys are to be remapped.
1269 */
1270 static void
1271change_remap_choice(int idx)
1272{
1273 remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
1274 alloc_text(idx, remap_text, remap_choices[remap_choice]);
1275}
1276
1277/*
1278 * Change the choice how to select text.
1279 */
1280 static void
1281change_mouse_choice(int idx)
1282{
1283 mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
1284 alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
1285}
1286
1287 static void
1288init_vimrc_choices(void)
1289{
1290 /* set path for a new _vimrc file (also when not used) */
1291 strcpy(vimrc, installdir);
1292 strcpy(vimrc + runtimeidx, "_vimrc");
1293
1294 /* Set opposite value and then toggle it by calling change_vimrc_choice() */
1295 if (*oldvimrc == NUL)
1296 choices[choice_count].installfunc = NULL;
1297 else
1298 choices[choice_count].installfunc = install_vimrc;
1299 choices[choice_count].text = NULL;
1300 change_vimrc_choice(choice_count);
1301 choices[choice_count].changefunc = change_vimrc_choice;
1302 choices[choice_count].active = 1;
1303 ++choice_count;
1304
1305 /* default way to run Vim */
1306 alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
1307 choices[choice_count].changefunc = change_run_choice;
1308 choices[choice_count].installfunc = NULL;
1309 choices[choice_count].active = (*oldvimrc == NUL);
1310 ++choice_count;
1311
1312 /* Whether to remap keys */
1313 alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
1314 choices[choice_count].changefunc = change_remap_choice;
Bram Moolenaar945ec092016-06-08 21:17:43 +02001315 choices[choice_count].installfunc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001316 choices[choice_count].active = (*oldvimrc == NUL);
1317 ++choice_count;
1318
1319 /* default way to use the mouse */
1320 alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
1321 choices[choice_count].changefunc = change_mouse_choice;
Bram Moolenaar945ec092016-06-08 21:17:43 +02001322 choices[choice_count].installfunc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001323 choices[choice_count].active = (*oldvimrc == NUL);
1324 ++choice_count;
1325}
1326
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001327#if defined(WIN3264)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001328 static LONG
1329reg_create_key(
1330 HKEY root,
1331 const char *subkey,
1332 PHKEY phKey)
1333{
1334 DWORD disp;
1335
1336 *phKey = NULL;
1337 return RegCreateKeyEx(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001338 root, subkey,
1339 0, NULL, REG_OPTION_NON_VOLATILE,
1340 KEY_WOW64_64KEY | KEY_WRITE,
1341 NULL, phKey, &disp);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001342}
1343
1344 static LONG
1345reg_set_string_value(
1346 HKEY hKey,
1347 const char *value_name,
1348 const char *data)
1349{
1350 return RegSetValueEx(hKey, value_name, 0, REG_SZ,
1351 (LPBYTE)data, (DWORD)(1 + strlen(data)));
1352}
1353
1354 static LONG
1355reg_create_key_and_value(
1356 HKEY hRootKey,
1357 const char *subkey,
1358 const char *value_name,
1359 const char *data)
1360{
1361 HKEY hKey;
1362 LONG lRet = reg_create_key(hRootKey, subkey, &hKey);
1363
1364 if (ERROR_SUCCESS == lRet)
1365 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001366 lRet = reg_set_string_value(hKey, value_name, data);
1367 RegCloseKey(hKey);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001368 }
1369 return lRet;
1370}
1371
1372 static LONG
1373register_inproc_server(
1374 HKEY hRootKey,
1375 const char *clsid,
1376 const char *extname,
1377 const char *module,
1378 const char *threading_model)
1379{
1380 CHAR subkey[BUFSIZE];
1381 LONG lRet;
1382
1383 sprintf(subkey, "CLSID\\%s", clsid);
1384 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, extname);
1385 if (ERROR_SUCCESS == lRet)
1386 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001387 sprintf(subkey, "CLSID\\%s\\InProcServer32", clsid);
1388 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, module);
1389 if (ERROR_SUCCESS == lRet)
1390 {
1391 lRet = reg_create_key_and_value(hRootKey, subkey,
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001392 "ThreadingModel", threading_model);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001393 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001394 }
1395 return lRet;
1396}
1397
1398 static LONG
1399register_shellex(
1400 HKEY hRootKey,
1401 const char *clsid,
1402 const char *name,
1403 const char *exe_path)
1404{
1405 LONG lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001406 hRootKey,
1407 "*\\shellex\\ContextMenuHandlers\\gvim",
1408 NULL,
1409 clsid);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001410
1411 if (ERROR_SUCCESS == lRet)
1412 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001413 lRet = reg_create_key_and_value(
1414 HKEY_LOCAL_MACHINE,
1415 "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1416 clsid,
1417 name);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001418
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001419 if (ERROR_SUCCESS == lRet)
1420 {
1421 lRet = reg_create_key_and_value(
1422 HKEY_LOCAL_MACHINE,
1423 "Software\\Vim\\Gvim",
1424 "path",
1425 exe_path);
1426 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001427 }
1428 return lRet;
1429}
1430
1431 static LONG
1432register_openwith(
1433 HKEY hRootKey,
1434 const char *exe_path)
1435{
Bram Moolenaar78050042010-07-31 20:53:54 +02001436 char exe_cmd[BUFSIZE];
1437 LONG lRet;
1438
Bram Moolenaarbbdcb482010-08-02 20:45:27 +02001439 sprintf(exe_cmd, "\"%s\" \"%%1\"", exe_path);
Bram Moolenaar78050042010-07-31 20:53:54 +02001440 lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001441 hRootKey,
1442 "Applications\\gvim.exe\\shell\\edit\\command",
1443 NULL,
Bram Moolenaar78050042010-07-31 20:53:54 +02001444 exe_cmd);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001445
1446 if (ERROR_SUCCESS == lRet)
1447 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001448 int i;
1449 static const char *openwith[] = {
1450 ".htm\\OpenWithList\\gvim.exe",
1451 ".vim\\OpenWithList\\gvim.exe",
1452 "*\\OpenWithList\\gvim.exe",
1453 };
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001454
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001455 for (i = 0; ERROR_SUCCESS == lRet
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001456 && i < sizeof(openwith) / sizeof(openwith[0]); i++)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001457 {
1458 lRet = reg_create_key_and_value(hRootKey, openwith[i], NULL, "");
1459 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001460 }
1461
1462 return lRet;
1463}
1464
1465 static LONG
1466register_uninstall(
1467 HKEY hRootKey,
1468 const char *appname,
1469 const char *display_name,
1470 const char *uninstall_string)
1471{
1472 LONG lRet = reg_create_key_and_value(hRootKey, appname,
1473 "DisplayName", display_name);
1474
1475 if (ERROR_SUCCESS == lRet)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001476 lRet = reg_create_key_and_value(hRootKey, appname,
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001477 "UninstallString", uninstall_string);
1478 return lRet;
1479}
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001480#endif /* WIN3264 */
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001481
Bram Moolenaar071d4272004-06-13 20:20:40 +00001482/*
1483 * Add some entries to the registry:
1484 * - to add "Edit with Vim" to the context * menu
1485 * - to add Vim to the "Open with..." list
1486 * - to uninstall Vim
1487 */
1488/*ARGSUSED*/
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001489 static int
Bram Moolenaar071d4272004-06-13 20:20:40 +00001490install_registry(void)
1491{
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001492#ifdef WIN3264
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001493 LONG lRet = ERROR_SUCCESS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001494 const char *vim_ext_ThreadingModel = "Apartment";
1495 const char *vim_ext_name = "Vim Shell Extension";
1496 const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001497 char vim_exe_path[BUFSIZE];
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001498 char display_name[BUFSIZE];
1499 char uninstall_string[BUFSIZE];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001500
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001501 sprintf(vim_exe_path, "%s\\gvim.exe", installdir);
1502
1503 if (install_popup)
1504 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001505 char bufg[BUFSIZE];
1506 struct stat st;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001507
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001508 if (stat("gvimext.dll", &st) >= 0)
1509 sprintf(bufg, "%s\\gvimext.dll", installdir);
1510 else
1511 /* gvimext.dll is in gvimext subdir */
1512 sprintf(bufg, "%s\\gvimext\\gvimext.dll", installdir);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001513
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001514 printf("Creating \"Edit with Vim\" popup menu entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001515
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001516 lRet = register_inproc_server(
1517 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name,
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001518 bufg, vim_ext_ThreadingModel);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001519 if (ERROR_SUCCESS != lRet)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001520 return FAIL;
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001521 lRet = register_shellex(
1522 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name, vim_exe_path);
1523 if (ERROR_SUCCESS != lRet)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001524 return FAIL;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001525 }
1526
1527 if (install_openwith)
1528 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001529 printf("Creating \"Open with ...\" list entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001530
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001531 lRet = register_openwith(HKEY_CLASSES_ROOT, vim_exe_path);
1532 if (ERROR_SUCCESS != lRet)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001533 return FAIL;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001534 }
1535
1536 printf("Creating an uninstall entry\n");
1537
1538 /* For the NSIS installer use the generated uninstaller. */
1539 if (interactive)
1540 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001541 sprintf(display_name, "Vim " VIM_VERSION_SHORT);
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001542 sprintf(uninstall_string, "%s\\uninstal.exe", installdir);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001543 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001544 else
1545 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001546 sprintf(display_name, "Vim " VIM_VERSION_SHORT " (self-installing)");
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001547 sprintf(uninstall_string, "%s\\uninstall-gui.exe", installdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001548 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001549
1550 lRet = register_uninstall(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001551 HKEY_LOCAL_MACHINE,
1552 "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT,
1553 display_name,
1554 uninstall_string);
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001555 if (ERROR_SUCCESS != lRet)
1556 return FAIL;
1557#endif /* WIN3264 */
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001558
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001559 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001560}
1561
1562 static void
1563change_popup_choice(int idx)
1564{
1565 if (install_popup == 0)
1566 {
1567 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";
1568 install_popup = 1;
1569 }
1570 else
1571 {
1572 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";
1573 install_popup = 0;
1574 }
1575}
1576
1577/*
1578 * Only add the choice for the popup menu entry when gvim.exe was found and
1579 * both gvimext.dll and regedit.exe exist.
1580 */
1581 static void
1582init_popup_choice(void)
1583{
1584 struct stat st;
1585
1586 if (has_gvim
1587 && (stat("gvimext.dll", &st) >= 0
1588 || stat("gvimext/gvimext.dll", &st) >= 0)
1589#ifndef WIN3264
1590 && searchpath("regedit.exe") != NULL
1591#endif
1592 )
1593 {
1594 choices[choice_count].changefunc = change_popup_choice;
1595 choices[choice_count].installfunc = NULL;
1596 choices[choice_count].active = 1;
1597 change_popup_choice(choice_count); /* set the text */
1598 ++choice_count;
1599 }
1600 else
1601 add_dummy_choice();
1602}
1603
1604 static void
1605change_openwith_choice(int idx)
1606{
1607 if (install_openwith == 0)
1608 {
1609 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";
1610 install_openwith = 1;
1611 }
1612 else
1613 {
1614 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";
1615 install_openwith = 0;
1616 }
1617}
1618
1619/*
1620 * Only add the choice for the open-with menu entry when gvim.exe was found
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001621 * and regedit.exe exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001622 */
1623 static void
1624init_openwith_choice(void)
1625{
1626 if (has_gvim
1627#ifndef WIN3264
1628 && searchpath("regedit.exe") != NULL
1629#endif
1630 )
1631 {
1632 choices[choice_count].changefunc = change_openwith_choice;
1633 choices[choice_count].installfunc = NULL;
1634 choices[choice_count].active = 1;
1635 change_openwith_choice(choice_count); /* set the text */
1636 ++choice_count;
1637 }
1638 else
1639 add_dummy_choice();
1640}
1641
1642#ifdef WIN3264
1643/* create_shortcut
1644 *
1645 * Create a shell link.
1646 *
1647 * returns 0 on failure, non-zero on successful completion.
1648 *
1649 * NOTE: Currently untested with mingw.
1650 */
1651 int
1652create_shortcut(
1653 const char *shortcut_name,
1654 const char *iconfile_path,
1655 int iconindex,
1656 const char *shortcut_target,
1657 const char *shortcut_args,
1658 const char *workingdir
1659 )
1660{
1661 IShellLink *shelllink_ptr;
1662 HRESULT hres;
1663 IPersistFile *persistfile_ptr;
1664
1665 /* Initialize COM library */
1666 hres = CoInitialize(NULL);
1667 if (!SUCCEEDED(hres))
1668 {
1669 printf("Error: Could not open the COM library. Not creating shortcut.\n");
1670 return FAIL;
1671 }
1672
1673 /* Instantiate a COM object for the ShellLink, store a pointer to it
1674 * in shelllink_ptr. */
1675 hres = CoCreateInstance(&CLSID_ShellLink,
1676 NULL,
1677 CLSCTX_INPROC_SERVER,
1678 &IID_IShellLink,
1679 (void **) &shelllink_ptr);
1680
1681 if (SUCCEEDED(hres)) /* If the instantiation was successful... */
1682 {
1683 /* ...Then build a PersistFile interface for the ShellLink so we can
1684 * save it as a file after we build it. */
1685 hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
1686 &IID_IPersistFile, (void **) &persistfile_ptr);
1687
1688 if (SUCCEEDED(hres))
1689 {
1690 wchar_t wsz[BUFSIZE];
1691
1692 /* translate the (possibly) multibyte shortcut filename to windows
1693 * Unicode so it can be used as a file name.
1694 */
1695 MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
1696
1697 /* set the attributes */
1698 shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
1699 shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
1700 workingdir);
1701 shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
1702 iconfile_path, iconindex);
1703 shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
1704
1705 /* save the shortcut to a file and return the PersistFile object*/
1706 persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
1707 persistfile_ptr->lpVtbl->Release(persistfile_ptr);
1708 }
1709 else
1710 {
1711 printf("QueryInterface Error\n");
1712 return FAIL;
1713 }
1714
1715 /* Return the ShellLink object */
1716 shelllink_ptr->lpVtbl->Release(shelllink_ptr);
1717 }
1718 else
1719 {
1720 printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
1721 return FAIL;
1722 }
1723
1724 return OK;
1725}
1726
1727/*
1728 * Build a path to where we will put a specified link.
1729 *
1730 * Return 0 on error, non-zero on success
1731 */
1732 int
1733build_link_name(
1734 char *link_path,
1735 const char *link_name,
1736 const char *shell_folder_name)
1737{
1738 char shell_folder_path[BUFSIZE];
1739
1740 if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
1741 {
1742 printf("An error occurred while attempting to find the path to %s.\n",
1743 shell_folder_name);
1744 return FAIL;
1745 }
1746
1747 /* Make sure the directory exists (create Start Menu\Programs\Vim).
1748 * Ignore errors if it already exists. */
1749 vim_mkdir(shell_folder_path, 0755);
1750
1751 /* build the path to the shortcut and the path to gvim.exe */
1752 sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
1753
1754 return OK;
1755}
1756
1757 static int
1758build_shortcut(
1759 const char *name, /* Name of the shortcut */
1760 const char *exename, /* Name of the executable (e.g., vim.exe) */
1761 const char *args,
1762 const char *shell_folder,
1763 const char *workingdir)
1764{
1765 char executable_path[BUFSIZE];
1766 char link_name[BUFSIZE];
1767
1768 sprintf(executable_path, "%s\\%s", installdir, exename);
1769
1770 if (build_link_name(link_name, name, shell_folder) == FAIL)
1771 {
1772 printf("An error has occurred. A shortcut to %s will not be created %s.\n",
1773 name,
1774 *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
1775 return FAIL;
1776 }
1777
1778 /* Create the shortcut: */
1779 return create_shortcut(link_name, executable_path, 0,
1780 executable_path, args, workingdir);
1781}
1782
1783/*
1784 * We used to use "homedir" as the working directory, but that is a bad choice
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001785 * on multi-user systems. However, not specifying a directory results in the
1786 * current directory to be c:\Windows\system32 on Windows 7. Use environment
1787 * variables instead.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001788 */
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001789#define WORKDIR "%HOMEDRIVE%%HOMEPATH%"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790
1791/*
1792 * Create shortcut(s) in the Start Menu\Programs\Vim folder.
1793 */
1794 static void
1795install_start_menu(int idx)
1796{
1797 need_uninstall_entry = 1;
1798 printf("Creating start menu\n");
1799 if (has_vim)
1800 {
1801 if (build_shortcut("Vim", "vim.exe", "",
1802 VIM_STARTMENU, WORKDIR) == FAIL)
1803 return;
1804 if (build_shortcut("Vim Read-only", "vim.exe", "-R",
1805 VIM_STARTMENU, WORKDIR) == FAIL)
1806 return;
1807 if (build_shortcut("Vim Diff", "vim.exe", "-d",
1808 VIM_STARTMENU, WORKDIR) == FAIL)
1809 return;
1810 }
1811 if (has_gvim)
1812 {
1813 if (build_shortcut("gVim", "gvim.exe", "",
1814 VIM_STARTMENU, WORKDIR) == FAIL)
1815 return;
1816 if (build_shortcut("gVim Easy", "gvim.exe", "-y",
1817 VIM_STARTMENU, WORKDIR) == FAIL)
1818 return;
1819 if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
1820 VIM_STARTMENU, WORKDIR) == FAIL)
1821 return;
1822 if (build_shortcut("gVim Diff", "gvim.exe", "-d",
1823 VIM_STARTMENU, WORKDIR) == FAIL)
1824 return;
1825 }
1826 if (build_shortcut("Uninstall",
1827 interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
1828 VIM_STARTMENU, installdir) == FAIL)
1829 return;
1830 /* For Windows NT the working dir of the vimtutor.bat must be right,
1831 * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
1832 if (build_shortcut("Vim tutor", "vimtutor.bat", "",
1833 VIM_STARTMENU, installdir) == FAIL)
1834 return;
1835 if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
1836 VIM_STARTMENU, WORKDIR) == FAIL)
1837 return;
1838 {
1839 char shell_folder_path[BUFSIZE];
1840
1841 /* Creating the URL shortcut works a bit differently... */
1842 if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
1843 {
1844 printf("Finding the path of the Start menu failed\n");
1845 return ;
1846 }
1847 add_pathsep(shell_folder_path);
1848 strcat(shell_folder_path, "Vim Online.url");
1849 if (!WritePrivateProfileString("InternetShortcut", "URL",
1850 "http://vim.sf.net/", shell_folder_path))
1851 {
1852 printf("Creating the Vim online URL failed\n");
1853 return;
1854 }
1855 }
1856}
1857
1858 static void
1859toggle_startmenu_choice(int idx)
1860{
1861 if (choices[idx].installfunc == NULL)
1862 {
1863 choices[idx].installfunc = install_start_menu;
1864 choices[idx].text = "Add Vim to the Start menu";
1865 }
1866 else
1867 {
1868 choices[idx].installfunc = NULL;
1869 choices[idx].text = "Do NOT add Vim to the Start menu";
1870 }
1871}
1872
1873/*
1874 * Function to actually create the shortcuts
1875 *
1876 * Currently I am supplying no working directory to the shortcut. This
1877 * means that the initial working dir will be:
1878 * - the location of the shortcut if no file is supplied
1879 * - the location of the file being edited if a file is supplied (ie via
1880 * drag and drop onto the shortcut).
1881 */
1882 void
1883install_shortcut_gvim(int idx)
1884{
1885 /* Create shortcut(s) on the desktop */
1886 if (choices[idx].arg)
1887 {
1888 (void)build_shortcut(icon_names[0], "gvim.exe",
1889 "", "desktop", WORKDIR);
1890 need_uninstall_entry = 1;
1891 }
1892}
1893
1894 void
1895install_shortcut_evim(int idx)
1896{
1897 if (choices[idx].arg)
1898 {
1899 (void)build_shortcut(icon_names[1], "gvim.exe",
1900 "-y", "desktop", WORKDIR);
1901 need_uninstall_entry = 1;
1902 }
1903}
1904
1905 void
1906install_shortcut_gview(int idx)
1907{
1908 if (choices[idx].arg)
1909 {
1910 (void)build_shortcut(icon_names[2], "gvim.exe",
1911 "-R", "desktop", WORKDIR);
1912 need_uninstall_entry = 1;
1913 }
1914}
1915
1916 void
1917toggle_shortcut_choice(int idx)
1918{
1919 char *arg;
1920
1921 if (choices[idx].installfunc == install_shortcut_gvim)
1922 arg = "gVim";
1923 else if (choices[idx].installfunc == install_shortcut_evim)
1924 arg = "gVim Easy";
1925 else
1926 arg = "gVim Read-only";
1927 if (choices[idx].arg)
1928 {
1929 choices[idx].arg = 0;
1930 alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
1931 }
1932 else
1933 {
1934 choices[idx].arg = 1;
1935 alloc_text(idx, "Create a desktop icon for %s", arg);
1936 }
1937}
1938#endif /* WIN3264 */
1939
1940 static void
1941init_startmenu_choice(void)
1942{
1943#ifdef WIN3264
1944 /* Start menu */
1945 choices[choice_count].changefunc = toggle_startmenu_choice;
1946 choices[choice_count].installfunc = NULL;
1947 choices[choice_count].active = 1;
1948 toggle_startmenu_choice(choice_count); /* set the text */
1949 ++choice_count;
1950#else
1951 add_dummy_choice();
1952#endif
1953}
1954
1955/*
1956 * Add the choice for the desktop shortcuts.
1957 */
1958 static void
1959init_shortcut_choices(void)
1960{
1961#ifdef WIN3264
1962 /* Shortcut to gvim */
1963 choices[choice_count].text = NULL;
1964 choices[choice_count].arg = 0;
1965 choices[choice_count].active = has_gvim;
1966 choices[choice_count].changefunc = toggle_shortcut_choice;
1967 choices[choice_count].installfunc = install_shortcut_gvim;
1968 toggle_shortcut_choice(choice_count);
1969 ++choice_count;
1970
1971 /* Shortcut to evim */
1972 choices[choice_count].text = NULL;
1973 choices[choice_count].arg = 0;
1974 choices[choice_count].active = has_gvim;
1975 choices[choice_count].changefunc = toggle_shortcut_choice;
1976 choices[choice_count].installfunc = install_shortcut_evim;
1977 toggle_shortcut_choice(choice_count);
1978 ++choice_count;
1979
1980 /* Shortcut to gview */
1981 choices[choice_count].text = NULL;
1982 choices[choice_count].arg = 0;
1983 choices[choice_count].active = has_gvim;
1984 choices[choice_count].changefunc = toggle_shortcut_choice;
1985 choices[choice_count].installfunc = install_shortcut_gview;
1986 toggle_shortcut_choice(choice_count);
1987 ++choice_count;
1988#else
1989 add_dummy_choice();
1990 add_dummy_choice();
1991 add_dummy_choice();
1992#endif
1993}
1994
1995#ifdef WIN3264
1996/*
1997 * Attempt to register OLE for Vim.
1998 */
1999 static void
2000install_OLE_register(void)
2001{
2002 char register_command_string[BUFSIZE + 30];
2003
2004 printf("\n--- Attempting to register Vim with OLE ---\n");
2005 printf("(There is no message whether this works or not.)\n");
2006
2007#ifndef __CYGWIN__
2008 sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
2009#else
2010 /* handle this differently for Cygwin which sometimes has trouble with
2011 * Windows-style pathnames here. */
2012 sprintf(register_command_string, "./gvim.exe -silent -register");
2013#endif
2014 system(register_command_string);
2015}
2016#endif /* WIN3264 */
2017
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");
2211 printf("-install-popup\n");
2212 printf(" Install the Edit-with-Vim context menu entry\n");
2213 printf("-install-openwith\n");
2214 printf(" Add Vim to the \"Open With...\" context menu list\n");
2215#ifdef WIN3264
2216 printf("-add-start-menu");
2217 printf(" Add Vim to the start menu\n");
2218 printf("-install-icons");
2219 printf(" Create icons for gVim executables on the desktop\n");
2220#endif
2221 printf("-create-directories [vim|home]\n");
2222 printf(" Create runtime directories to drop plugins into; in the $VIM\n");
2223 printf(" or $HOME directory\n");
2224#ifdef WIN3264
2225 printf("-register-OLE");
Bram Moolenaarce0842a2005-07-18 21:58:11 +00002226 printf(" Ignored\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227#endif
2228 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 }
2270 else if (strcmp(argv[i], "-install-popup") == 0)
2271 {
2272 init_popup_choice();
2273 }
2274 else if (strcmp(argv[i], "-install-openwith") == 0)
2275 {
2276 init_openwith_choice();
2277 }
2278 else if (strcmp(argv[i], "-add-start-menu") == 0)
2279 {
2280 init_startmenu_choice();
2281 }
2282 else if (strcmp(argv[i], "-install-icons") == 0)
2283 {
2284 init_shortcut_choices();
2285 }
2286 else if (strcmp(argv[i], "-create-directories") == 0)
2287 {
2288 init_directories_choice();
2289 if (argv[i + 1][0] != '-')
2290 {
2291 i++;
2292 if (strcmp(argv[i], "vim") == 0)
2293 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2294 else if (strcmp(argv[i], "home") == 0)
2295 {
2296 if (getenv("HOME") == NULL) /* No $HOME in environment */
2297 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2298 else
2299 vimfiles_dir_choice = (int)vimfiles_dir_home;
2300 }
2301 else
2302 {
2303 printf("Unknown argument for -create-directories: %s\n",
2304 argv[i]);
2305 print_cmd_line_help();
2306 }
2307 }
2308 else /* No choice specified, default to vim directory */
2309 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2310 }
2311#ifdef WIN3264
2312 else if (strcmp(argv[i], "-register-OLE") == 0)
2313 {
2314 /* This is always done when gvim is found */
2315 }
2316#endif
2317 else /* Unknown switch */
2318 {
2319 printf("Got unknown argument argv[%d] = %s\n", i, argv[i]);
2320 print_cmd_line_help();
2321 }
2322 }
2323}
2324
2325
2326/*
2327 * Show a few screens full of helpful information.
2328 */
2329 static void
2330show_help(void)
2331{
2332 static char *(items[]) =
2333 {
2334"Installing .bat files\n"
2335"---------------------\n"
2336"The vim.bat file is written in one of the directories in $PATH.\n"
2337"This makes it possible to start Vim from the command line.\n"
2338"If vim.exe can be found in $PATH, the choice for vim.bat will not be\n"
2339"present. It is assumed you will use the existing vim.exe.\n"
2340"If vim.bat can already be found in $PATH this is probably for an old\n"
2341"version of Vim (but this is not checked!). You can overwrite it.\n"
2342"If no vim.bat already exists, you can select one of the directories in\n"
2343"$PATH for creating the batch file, or disable creating a vim.bat file.\n"
2344"\n"
2345"If you choose not to create the vim.bat file, Vim can still be executed\n"
2346"in other ways, but not from the command line.\n"
2347"\n"
2348"The same applies to choices for gvim, evim, (g)view, and (g)vimdiff.\n"
2349"The first item can be used to change the path for all of them.\n"
2350,
2351"Creating a _vimrc file\n"
2352"----------------------\n"
2353"The _vimrc file is used to set options for how Vim behaves.\n"
2354"The install program can create a _vimrc file with a few basic choices.\n"
2355"You can edit this file later to tune your preferences.\n"
2356"If you already have a _vimrc or .vimrc file it can be overwritten.\n"
2357"Don't do that if you have made changes to it.\n"
2358,
2359"Vim features\n"
2360"------------\n"
2361"(this choice is only available when creating a _vimrc file)\n"
2362"1. Vim can run in Vi-compatible mode. Many nice Vim features are then\n"
2363" disabled. In the not-Vi-compatible mode Vim is still mostly Vi\n"
2364" compatible, but adds nice features like multi-level undo. Only\n"
2365" choose Vi-compatible if you really need full Vi compatibility.\n"
2366"2. Running Vim with some enhancements is useful when you want some of\n"
2367" the nice Vim features, but have a slow computer and want to keep it\n"
2368" really fast.\n"
2369"3. Syntax highlighting shows many files in color. Not only does this look\n"
2370" nice, it also makes it easier to spot errors and you can work faster.\n"
2371" The other features include editing compressed files.\n"
2372,
2373"Windows key mapping\n"
2374"-------------------\n"
2375"(this choice is only available when creating a _vimrc file)\n"
2376"Under MS-Windows the CTRL-C key copies text to the clipboard and CTRL-V\n"
2377"pastes text from the clipboard. There are a few more keys like these.\n"
2378"Unfortunately, in Vim these keys normally have another meaning.\n"
2379"1. Choose to have the keys like they normally are in Vim (useful if you\n"
2380" also use Vim on other systems).\n"
2381"2. Choose to have the keys work like they are used on MS-Windows (useful\n"
2382" if you mostly work on MS-Windows).\n"
2383,
2384"Mouse use\n"
2385"---------\n"
2386"(this choice is only available when creating a _vimrc file)\n"
2387"The right mouse button can be used in two ways:\n"
2388"1. The Unix way is to extend an existing selection. The popup menu is\n"
2389" not available.\n"
2390"2. The MS-Windows way is to show a popup menu, which allows you to\n"
2391" copy/paste text, undo/redo, etc. Extending the selection can still be\n"
2392" done by keeping SHIFT pressed while using the left mouse button\n"
2393,
2394"Edit-with-Vim context menu entry\n"
2395"--------------------------------\n"
2396"(this choice is only available when gvim.exe and gvimext.dll are present)\n"
2397"You can associate different file types with Vim, so that you can (double)\n"
2398"click on a file to edit it with Vim. This means you have to individually\n"
2399"select each file type.\n"
2400"An alternative is the option offered here: Install an \"Edit with Vim\"\n"
2401"entry in the popup menu for the right mouse button. This means you can\n"
2402"edit any file with Vim.\n"
2403,
2404"\"Open With...\" context menu entry\n"
2405"--------------------------------\n"
2406"(this choice is only available when gvim.exe is present)\n"
2407"This option adds Vim to the \"Open With...\" entry in the popup menu for\n"
2408"the right mouse button. This also makes it possible to edit HTML files\n"
2409"directly from Internet Explorer.\n"
2410,
2411"Add Vim to the Start menu\n"
2412"-------------------------\n"
2413"In Windows 95 and later, Vim can be added to the Start menu. This will\n"
2414"create a submenu with an entry for vim, gvim, evim, vimdiff, etc..\n"
2415,
2416"Icons on the desktop\n"
2417"--------------------\n"
2418"(these choices are only available when installing gvim)\n"
2419"In Windows 95 and later, shortcuts (icons) can be created on the Desktop.\n"
2420,
2421"Create plugin directories\n"
2422"-------------------------\n"
2423"Plugin directories allow extending Vim by dropping a file into a directory.\n"
2424"This choice allows creating them in $HOME (if you have a home directory) or\n"
2425"$VIM (used for everybody on the system).\n"
2426,
2427NULL
2428 };
2429 int i;
2430 int c;
2431
2432 rewind(stdin);
2433 printf("\n");
2434 for (i = 0; items[i] != NULL; ++i)
2435 {
2436 printf(items[i]);
2437 printf("\n");
2438 printf("Hit Enter to continue, b (back) or q (quit help): ");
2439 c = getchar();
2440 rewind(stdin);
2441 if (c == 'b' || c == 'B')
2442 {
2443 if (i == 0)
2444 --i;
2445 else
2446 i -= 2;
2447 }
2448 if (c == 'q' || c == 'Q')
2449 break;
2450 printf("\n");
2451 }
2452}
2453
2454/*
2455 * Install the choices.
2456 */
2457 static void
2458install(void)
2459{
2460 int i;
2461
2462 /* Install the selected choices. */
2463 for (i = 0; i < choice_count; ++i)
2464 if (choices[i].installfunc != NULL && choices[i].active)
2465 (choices[i].installfunc)(i);
2466
2467 /* Add some entries to the registry, if needed. */
2468 if (install_popup
2469 || install_openwith
2470 || (need_uninstall_entry && interactive)
2471 || !interactive)
2472 install_registry();
2473
2474#ifdef WIN3264
2475 /* Register gvim with OLE. */
2476 if (has_gvim)
2477 install_OLE_register();
2478#endif
2479}
2480
2481/*
2482 * request_choice
2483 */
2484 static void
2485request_choice(void)
2486{
2487 int i;
2488
2489 printf("\n\nInstall will do for you:\n");
2490 for (i = 0; i < choice_count; ++i)
2491 if (choices[i].active)
2492 printf("%2d %s\n", i + 1, choices[i].text);
2493 printf("To change an item, enter its number\n\n");
2494 printf("Enter item number, h (help), d (do it) or q (quit): ");
2495}
2496
2497 int
2498main(int argc, char **argv)
2499{
2500 int i;
2501 char buf[BUFSIZE];
2502
2503 /*
2504 * Run interactively if there are no command line arguments.
2505 */
2506 if (argc > 1)
2507 interactive = 0;
2508 else
2509 interactive = 1;
2510
2511 /* Initialize this program. */
2512 do_inits(argv);
2513
2514#ifdef WIN3264
2515 if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
2516 {
2517 /* Only check for already installed Vims. Used by NSIS installer. */
Bram Moolenaar442b4222010-05-24 21:34:22 +02002518 i = uninstall_check(1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519
2520 /* Find the value of $VIM, because NSIS isn't able to do this by
2521 * itself. */
2522 get_vim_env();
2523
2524 /* When nothing found exit quietly. If something found wait for
Bram Moolenaarb230bd52010-05-25 21:02:00 +02002525 * a little while, so that the user can read the messages. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002526 if (i)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002527 sleep(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528 exit(0);
2529 }
2530#endif
2531
2532 printf("This program sets up the installation of Vim "
2533 VIM_VERSION_MEDIUM "\n\n");
2534
2535 /* Check if the user unpacked the archives properly. */
2536 check_unpack();
2537
2538#ifdef WIN3264
2539 /* Check for already installed Vims. */
2540 if (interactive)
Bram Moolenaar442b4222010-05-24 21:34:22 +02002541 uninstall_check(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542#endif
2543
2544 /* Find out information about the system. */
2545 inspect_system();
2546
2547 if (interactive)
2548 {
2549 /* Setup all the choices. */
2550 setup_choices();
2551
2552 /* Let the user change choices and finally install (or quit). */
2553 for (;;)
2554 {
2555 request_choice();
2556 rewind(stdin);
2557 if (scanf("%99s", buf) == 1)
2558 {
2559 if (isdigit(buf[0]))
2560 {
2561 /* Change a choice. */
2562 i = atoi(buf);
2563 if (i > 0 && i <= choice_count && choices[i - 1].active)
2564 (choices[i - 1].changefunc)(i - 1);
2565 else
2566 printf("\nIllegal choice\n");
2567 }
2568 else if (buf[0] == 'h' || buf[0] == 'H')
2569 {
2570 /* Help */
2571 show_help();
2572 }
2573 else if (buf[0] == 'd' || buf[0] == 'D')
2574 {
2575 /* Install! */
2576 install();
2577 printf("\nThat finishes the installation. Happy Vimming!\n");
2578 break;
2579 }
2580 else if (buf[0] == 'q' || buf[0] == 'Q')
2581 {
2582 /* Quit */
2583 printf("\nExiting without anything done\n");
2584 break;
2585 }
2586 else
2587 printf("\nIllegal choice\n");
2588 }
2589 }
2590 printf("\n");
Bram Moolenaar442b4222010-05-24 21:34:22 +02002591 myexit(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002592 }
2593 else
2594 {
2595 /*
2596 * Run non-interactive - setup according to the command line switches
2597 */
2598 command_line_setup_choices(argc, argv);
2599 install();
Bram Moolenaar442b4222010-05-24 21:34:22 +02002600
2601 /* Avoid that the user has to hit Enter, just wait a little bit to
2602 * allow reading the messages. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002603 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604 }
2605
Bram Moolenaar071d4272004-06-13 20:20:40 +00002606 return 0;
2607}