blob: 3fbfb5c5c2e13c84d06048c0470a6e935555e416 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
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 Moolenaar071d4272004-06-13 20:20:40 +0000765
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000766 /* Don't use double quotes for the "set" argument, also when it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767 * contains a space. The quotes would be included in the value
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000768 * for MSDOS and NT.
769 * The order of preference is:
770 * 1. $VIMRUNTIME/vim.exe (user preference)
771 * 2. $VIM/vim70/vim.exe (hard coded version)
772 * 3. installdir/vim.exe (hard coded install directory)
773 */
774 fprintf(fd, "set VIM_EXE_DIR=%s\n", installdir);
775 fprintf(fd, "if exist \"%%VIM%%\\%s\\%s\" set VIM_EXE_DIR=%%VIM%%\\%s\n",
776 VIM_VERSION_NODOT, exename, VIM_VERSION_NODOT);
777 fprintf(fd, "if exist \"%%VIMRUNTIME%%\\%s\" set VIM_EXE_DIR=%%VIMRUNTIME%%\n", exename);
778 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779
780 /* Give an error message when the executable could not be found. */
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000781 fprintf(fd, "if exist \"%%VIM_EXE_DIR%%\\%s\" goto havevim\n",
782 exename);
783 fprintf(fd, "echo \"%%VIM_EXE_DIR%%\\%s\" not found\n", exename);
784 fprintf(fd, "goto eof\n");
785 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 fprintf(fd, ":havevim\n");
787
788 fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
789 fprintf(fd, "set VIMARGS=\n");
790 if (*exename == 'g')
791 fprintf(fd, "set VIMNOFORK=\n");
792 fprintf(fd, ":loopstart\n");
793 fprintf(fd, "if .%%1==. goto loopend\n");
794 if (*exename == 'g')
795 {
796 fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
797 fprintf(fd, "set VIMNOFORK=1\n");
798 fprintf(fd, ":noforkarg\n");
799 }
800 fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
801 fprintf(fd, "shift\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000802 fprintf(fd, "goto loopstart\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 fprintf(fd, ":loopend\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000804 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000806 fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n");
807 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808
809 /* For gvim.exe use "start" to avoid that the console window stays
810 * open. */
811 if (*exename == 'g')
812 {
813 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
814 fprintf(fd, "start ");
815 }
816
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000817 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
818 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
819 exename, vimarg);
820 fprintf(fd, "goto eof\n");
821 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822
823 if (*exename == 'g')
824 {
825 fprintf(fd, ":nofork\n");
826 fprintf(fd, "start /w ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000827 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
828 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
829 exename, vimarg);
830 fprintf(fd, "goto eof\n");
831 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 }
833
834 fprintf(fd, ":ntaction\n");
835 fprintf(fd, "rem for WinNT we can use %%*\n");
836
837 /* For gvim.exe use "start /b" to avoid that the console window
838 * stays open. */
839 if (*exename == 'g')
840 {
841 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
842 fprintf(fd, "start \"dummy\" /b ");
843 }
844
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000845 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
846 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n", exename, vimarg);
847 fprintf(fd, "goto eof\n");
848 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849
850 if (*exename == 'g')
851 {
852 fprintf(fd, ":noforknt\n");
853 fprintf(fd, "start \"dummy\" /b /wait ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000854 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
855 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n",
856 exename, vimarg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857 }
858
859 fprintf(fd, "\n:eof\n");
860 fprintf(fd, "set VIMARGS=\n");
861 if (*exename == 'g')
862 fprintf(fd, "set VIMNOFORK=\n");
863
864 fclose(fd);
865 printf("%s has been %s\n", batpath,
866 oldname == NULL ? "created" : "overwritten");
867 }
868 }
869}
870
871/*
872 * Make the text string for choice "idx".
873 * The format "fmt" is must have one %s item, which "arg" is used for.
874 */
875 static void
876alloc_text(int idx, char *fmt, char *arg)
877{
878 if (choices[idx].text != NULL)
879 free(choices[idx].text);
880
881 choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
882 sprintf(choices[idx].text, fmt, arg);
883}
884
885/*
886 * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
887 */
888 static void
889toggle_bat_choice(int idx)
890{
891 char *batname = targets[choices[idx].arg].batpath;
892 char *oldname = targets[choices[idx].arg].oldbat;
893
894 if (*batname == NUL)
895 {
896 alloc_text(idx, " Overwrite %s", oldname);
897 strcpy(batname, oldname);
898 }
899 else
900 {
901 alloc_text(idx, " Do NOT overwrite %s", oldname);
902 *batname = NUL;
903 }
904}
905
906/*
907 * Do some work for a batch file entry: Append the batch file name to the path
908 * and set the text for the choice.
909 */
910 static void
911set_bat_text(int idx, char *batpath, char *name)
912{
913 strcat(batpath, name);
914
915 alloc_text(idx, " Create %s", batpath);
916}
917
918/*
919 * Select a directory to write the batch file line.
920 */
921 static void
922change_bat_choice(int idx)
923{
924 char *path;
925 char *batpath;
926 char *name;
927 int n;
928 char *s;
929 char *p;
930 int count;
931 char **names = NULL;
932 int i;
933 int target = choices[idx].arg;
934
935 name = targets[target].batname;
936 batpath = targets[target].batpath;
937
938 path = getenv("PATH");
939 if (path == NULL)
940 {
941 printf("\nERROR: The variable $PATH is not set\n");
942 return;
943 }
944
945 /*
946 * first round: count number of names in path;
947 * second round: save names to names[].
948 */
949 for (;;)
950 {
951 count = 1;
952 for (p = path; *p; )
953 {
954 s = strchr(p, ';');
955 if (s == NULL)
956 s = p + strlen(p);
957 if (names != NULL)
958 {
959 names[count] = alloc((int)(s - p) + 1);
960 strncpy(names[count], p, s - p);
961 names[count][s - p] = NUL;
962 }
963 ++count;
964 p = s;
965 if (*p != NUL)
966 ++p;
967 }
968 if (names != NULL)
969 break;
970 names = alloc((int)(count + 1) * sizeof(char *));
971 }
972 names[0] = alloc(50);
973 sprintf(names[0], "Select directory to create %s in:", name);
974 names[count] = alloc(50);
975 if (choices[idx].arg == 0)
976 sprintf(names[count], "Do not create any .bat file.");
977 else
978 sprintf(names[count], "Do not create a %s file.", name);
979 n = get_choice(names, count + 1);
980
981 if (n == count)
982 {
983 /* Selected last item, don't create bat file. */
984 *batpath = NUL;
985 if (choices[idx].arg != 0)
986 alloc_text(idx, " Do NOT create %s", name);
987 }
988 else
989 {
990 /* Selected one of the paths. For the first item only keep the path,
991 * for the others append the batch file name. */
992 strcpy(batpath, names[n]);
993 add_pathsep(batpath);
994 if (choices[idx].arg != 0)
995 set_bat_text(idx, batpath, name);
996 }
997
998 for (i = 0; i <= count; ++i)
999 free(names[i]);
1000 free(names);
1001}
1002
1003char *bat_text_yes = "Install .bat files to use Vim at the command line:";
1004char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
1005
1006 static void
1007change_main_bat_choice(int idx)
1008{
1009 int i;
1010
1011 /* let the user select a default directory or NONE */
1012 change_bat_choice(idx);
1013
1014 if (targets[0].batpath[0] != NUL)
1015 choices[idx].text = bat_text_yes;
1016 else
1017 choices[idx].text = bat_text_no;
1018
1019 /* update the individual batch file selections */
1020 for (i = 1; i < TARGET_COUNT; ++i)
1021 {
1022 /* Only make it active when the first item has a path and the vim.exe
1023 * or gvim.exe exists (there is a changefunc then). */
1024 if (targets[0].batpath[0] != NUL
1025 && choices[idx + i].changefunc != NULL)
1026 {
1027 choices[idx + i].active = 1;
1028 if (choices[idx + i].changefunc == change_bat_choice
1029 && targets[i].batpath[0] != NUL)
1030 {
1031 strcpy(targets[i].batpath, targets[0].batpath);
1032 set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
1033 }
1034 }
1035 else
1036 choices[idx + i].active = 0;
1037 }
1038}
1039
1040/*
1041 * Initialize a choice for creating a batch file.
1042 */
1043 static void
1044init_bat_choice(int target)
1045{
1046 char *batpath = targets[target].batpath;
1047 char *oldbat = targets[target].oldbat;
1048 char *p;
1049 int i;
1050
1051 choices[choice_count].arg = target;
1052 choices[choice_count].installfunc = install_bat_choice;
1053 choices[choice_count].active = 1;
1054 choices[choice_count].text = NULL; /* will be set below */
1055 if (oldbat != NULL)
1056 {
1057 /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
1058 choices[choice_count].changefunc = toggle_bat_choice;
1059 *batpath = NUL;
1060 toggle_bat_choice(choice_count);
1061 }
1062 else
1063 {
1064 if (default_bat_dir != NULL)
1065 /* Prefer using the same path as an existing .bat file. */
1066 strcpy(batpath, default_bat_dir);
1067 else
1068 {
1069 /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
1070 * $WINDIR by default, if it's empty the first item in $PATH. */
1071 p = getenv("WINDIR");
1072 if (p != NULL && *p != NUL)
1073 strcpy(batpath, p);
1074 else
1075 {
1076 p = getenv("PATH");
1077 if (p == NULL || *p == NUL) /* "cannot happen" */
1078 strcpy(batpath, "C:/Windows");
1079 else
1080 {
1081 i = 0;
1082 while (*p != NUL && *p != ';')
1083 batpath[i++] = *p++;
1084 batpath[i] = NUL;
1085 }
1086 }
1087 }
1088 add_pathsep(batpath);
1089 set_bat_text(choice_count, batpath, targets[target].batname);
1090
1091 choices[choice_count].changefunc = change_bat_choice;
1092 }
1093 ++choice_count;
1094}
1095
1096/*
1097 * Set up the choices for installing .bat files.
1098 * For these items "arg" is the index in targets[].
1099 */
1100 static void
1101init_bat_choices(void)
1102{
1103 int i;
1104
1105 /* The first item is used to switch installing batch files on/off and
1106 * setting the default path. */
1107 choices[choice_count].text = bat_text_yes;
1108 choices[choice_count].changefunc = change_main_bat_choice;
1109 choices[choice_count].installfunc = NULL;
1110 choices[choice_count].active = 1;
1111 choices[choice_count].arg = 0;
1112 ++choice_count;
1113
1114 /* Add items for each batch file target. Only used when not disabled by
1115 * the first item. When a .exe exists, don't offer to create a .bat. */
1116 for (i = 1; i < TARGET_COUNT; ++i)
1117 if (targets[i].oldexe == NULL
1118 && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
1119 init_bat_choice(i);
1120 else
1121 add_dummy_choice();
1122}
1123
1124/*
1125 * Install the vimrc file.
1126 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001127 static void
1128install_vimrc(int idx)
1129{
1130 FILE *fd, *tfd;
1131 char *fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001132
1133 /* If an old vimrc file exists, overwrite it.
1134 * Otherwise create a new one. */
1135 if (*oldvimrc != NUL)
1136 fname = oldvimrc;
1137 else
1138 fname = vimrc;
1139
1140 fd = fopen(fname, "w");
1141 if (fd == NULL)
1142 {
1143 printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
1144 return;
1145 }
1146 switch (compat_choice)
1147 {
1148 case compat_vi:
1149 fprintf(fd, "set compatible\n");
1150 break;
1151 case compat_some_enhancements:
1152 fprintf(fd, "set nocompatible\n");
1153 break;
1154 case compat_all_enhancements:
1155 fprintf(fd, "set nocompatible\n");
1156 fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
1157 break;
1158 }
1159 switch (remap_choice)
1160 {
1161 case remap_no:
1162 break;
1163 case remap_win:
1164 fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
1165 break;
1166 }
1167 switch (mouse_choice)
1168 {
1169 case mouse_xterm:
1170 fprintf(fd, "behave xterm\n");
1171 break;
1172 case mouse_mswin:
1173 fprintf(fd, "behave mswin\n");
1174 break;
1175 }
1176 if ((tfd = fopen("diff.exe", "r")) != NULL)
1177 {
1178 /* Use the diff.exe that comes with the self-extracting gvim.exe. */
1179 fclose(tfd);
1180 fprintf(fd, "\n");
1181 fprintf(fd, "set diffexpr=MyDiff()\n");
1182 fprintf(fd, "function MyDiff()\n");
1183 fprintf(fd, " let opt = '-a --binary '\n");
1184 fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
1185 fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
1186 /* Use quotes only when needed, they may cause trouble. */
1187 fprintf(fd, " let arg1 = v:fname_in\n");
1188 fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
1189 fprintf(fd, " let arg2 = v:fname_new\n");
1190 fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
1191 fprintf(fd, " let arg3 = v:fname_out\n");
1192 fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001193
1194 /* If the path has a space: When using cmd.exe (Win NT/2000/XP) put
1195 * quotes around the whole command and around the diff command.
1196 * Otherwise put a double quote just before the space and at the
1197 * end of the command. Putting quotes around the whole thing
1198 * doesn't work on Win 95/98/ME. This is mostly guessed! */
1199 fprintf(fd, " let eq = ''\n");
1200 fprintf(fd, " if $VIMRUNTIME =~ ' '\n");
1201 fprintf(fd, " if &sh =~ '\\<cmd'\n");
1202 fprintf(fd, " let cmd = '\"\"' . $VIMRUNTIME . '\\diff\"'\n");
1203 fprintf(fd, " let eq = '\"'\n");
1204 fprintf(fd, " else\n");
1205 fprintf(fd, " let cmd = substitute($VIMRUNTIME, ' ', '\" ', '') . '\\diff\"'\n");
1206 fprintf(fd, " endif\n");
1207 fprintf(fd, " else\n");
1208 fprintf(fd, " let cmd = $VIMRUNTIME . '\\diff'\n");
1209 fprintf(fd, " endif\n");
1210 fprintf(fd, " silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq\n");
1211
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212 fprintf(fd, "endfunction\n");
1213 fprintf(fd, "\n");
1214 }
1215 fclose(fd);
1216 printf("%s has been written\n", fname);
1217}
1218
1219 static void
1220change_vimrc_choice(int idx)
1221{
1222 if (choices[idx].installfunc != NULL)
1223 {
1224 /* Switch to NOT change or create a vimrc file. */
1225 if (*oldvimrc != NUL)
1226 alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
1227 else
1228 alloc_text(idx, "Do NOT create startup file %s", vimrc);
1229 choices[idx].installfunc = NULL;
1230 choices[idx + 1].active = 0;
1231 choices[idx + 2].active = 0;
1232 choices[idx + 3].active = 0;
1233 }
1234 else
1235 {
1236 /* Switch to change or create a vimrc file. */
1237 if (*oldvimrc != NUL)
1238 alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
1239 else
1240 alloc_text(idx, "Create startup file %s with:", vimrc);
1241 choices[idx].installfunc = install_vimrc;
1242 choices[idx + 1].active = 1;
1243 choices[idx + 2].active = 1;
1244 choices[idx + 3].active = 1;
1245 }
1246}
1247
1248/*
1249 * Change the choice how to run Vim.
1250 */
1251 static void
1252change_run_choice(int idx)
1253{
1254 compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
1255 alloc_text(idx, compat_text, compat_choices[compat_choice]);
1256}
1257
1258/*
1259 * Change the choice if keys are to be remapped.
1260 */
1261 static void
1262change_remap_choice(int idx)
1263{
1264 remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
1265 alloc_text(idx, remap_text, remap_choices[remap_choice]);
1266}
1267
1268/*
1269 * Change the choice how to select text.
1270 */
1271 static void
1272change_mouse_choice(int idx)
1273{
1274 mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
1275 alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
1276}
1277
1278 static void
1279init_vimrc_choices(void)
1280{
1281 /* set path for a new _vimrc file (also when not used) */
1282 strcpy(vimrc, installdir);
1283 strcpy(vimrc + runtimeidx, "_vimrc");
1284
1285 /* Set opposite value and then toggle it by calling change_vimrc_choice() */
1286 if (*oldvimrc == NUL)
1287 choices[choice_count].installfunc = NULL;
1288 else
1289 choices[choice_count].installfunc = install_vimrc;
1290 choices[choice_count].text = NULL;
1291 change_vimrc_choice(choice_count);
1292 choices[choice_count].changefunc = change_vimrc_choice;
1293 choices[choice_count].active = 1;
1294 ++choice_count;
1295
1296 /* default way to run Vim */
1297 alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
1298 choices[choice_count].changefunc = change_run_choice;
1299 choices[choice_count].installfunc = NULL;
1300 choices[choice_count].active = (*oldvimrc == NUL);
1301 ++choice_count;
1302
1303 /* Whether to remap keys */
1304 alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
1305 choices[choice_count].changefunc = change_remap_choice;
1306 choices[choice_count].installfunc = NULL;;
1307 choices[choice_count].active = (*oldvimrc == NUL);
1308 ++choice_count;
1309
1310 /* default way to use the mouse */
1311 alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
1312 choices[choice_count].changefunc = change_mouse_choice;
1313 choices[choice_count].installfunc = NULL;;
1314 choices[choice_count].active = (*oldvimrc == NUL);
1315 ++choice_count;
1316}
1317
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001318#if defined(WIN3264)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001319 static LONG
1320reg_create_key(
1321 HKEY root,
1322 const char *subkey,
1323 PHKEY phKey)
1324{
1325 DWORD disp;
1326
1327 *phKey = NULL;
1328 return RegCreateKeyEx(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001329 root, subkey,
1330 0, NULL, REG_OPTION_NON_VOLATILE,
1331 KEY_WOW64_64KEY | KEY_WRITE,
1332 NULL, phKey, &disp);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001333}
1334
1335 static LONG
1336reg_set_string_value(
1337 HKEY hKey,
1338 const char *value_name,
1339 const char *data)
1340{
1341 return RegSetValueEx(hKey, value_name, 0, REG_SZ,
1342 (LPBYTE)data, (DWORD)(1 + strlen(data)));
1343}
1344
1345 static LONG
1346reg_create_key_and_value(
1347 HKEY hRootKey,
1348 const char *subkey,
1349 const char *value_name,
1350 const char *data)
1351{
1352 HKEY hKey;
1353 LONG lRet = reg_create_key(hRootKey, subkey, &hKey);
1354
1355 if (ERROR_SUCCESS == lRet)
1356 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001357 lRet = reg_set_string_value(hKey, value_name, data);
1358 RegCloseKey(hKey);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001359 }
1360 return lRet;
1361}
1362
1363 static LONG
1364register_inproc_server(
1365 HKEY hRootKey,
1366 const char *clsid,
1367 const char *extname,
1368 const char *module,
1369 const char *threading_model)
1370{
1371 CHAR subkey[BUFSIZE];
1372 LONG lRet;
1373
1374 sprintf(subkey, "CLSID\\%s", clsid);
1375 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, extname);
1376 if (ERROR_SUCCESS == lRet)
1377 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001378 sprintf(subkey, "CLSID\\%s\\InProcServer32", clsid);
1379 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, module);
1380 if (ERROR_SUCCESS == lRet)
1381 {
1382 lRet = reg_create_key_and_value(hRootKey, subkey,
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001383 "ThreadingModel", threading_model);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001384 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001385 }
1386 return lRet;
1387}
1388
1389 static LONG
1390register_shellex(
1391 HKEY hRootKey,
1392 const char *clsid,
1393 const char *name,
1394 const char *exe_path)
1395{
1396 LONG lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001397 hRootKey,
1398 "*\\shellex\\ContextMenuHandlers\\gvim",
1399 NULL,
1400 clsid);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001401
1402 if (ERROR_SUCCESS == lRet)
1403 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001404 lRet = reg_create_key_and_value(
1405 HKEY_LOCAL_MACHINE,
1406 "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1407 clsid,
1408 name);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001409
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001410 if (ERROR_SUCCESS == lRet)
1411 {
1412 lRet = reg_create_key_and_value(
1413 HKEY_LOCAL_MACHINE,
1414 "Software\\Vim\\Gvim",
1415 "path",
1416 exe_path);
1417 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001418 }
1419 return lRet;
1420}
1421
1422 static LONG
1423register_openwith(
1424 HKEY hRootKey,
1425 const char *exe_path)
1426{
Bram Moolenaar78050042010-07-31 20:53:54 +02001427 char exe_cmd[BUFSIZE];
1428 LONG lRet;
1429
Bram Moolenaarbbdcb482010-08-02 20:45:27 +02001430 sprintf(exe_cmd, "\"%s\" \"%%1\"", exe_path);
Bram Moolenaar78050042010-07-31 20:53:54 +02001431 lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001432 hRootKey,
1433 "Applications\\gvim.exe\\shell\\edit\\command",
1434 NULL,
Bram Moolenaar78050042010-07-31 20:53:54 +02001435 exe_cmd);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001436
1437 if (ERROR_SUCCESS == lRet)
1438 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001439 int i;
1440 static const char *openwith[] = {
1441 ".htm\\OpenWithList\\gvim.exe",
1442 ".vim\\OpenWithList\\gvim.exe",
1443 "*\\OpenWithList\\gvim.exe",
1444 };
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001445
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001446 for (i = 0; ERROR_SUCCESS == lRet
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001447 && i < sizeof(openwith) / sizeof(openwith[0]); i++)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001448 {
1449 lRet = reg_create_key_and_value(hRootKey, openwith[i], NULL, "");
1450 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001451 }
1452
1453 return lRet;
1454}
1455
1456 static LONG
1457register_uninstall(
1458 HKEY hRootKey,
1459 const char *appname,
1460 const char *display_name,
1461 const char *uninstall_string)
1462{
1463 LONG lRet = reg_create_key_and_value(hRootKey, appname,
1464 "DisplayName", display_name);
1465
1466 if (ERROR_SUCCESS == lRet)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001467 lRet = reg_create_key_and_value(hRootKey, appname,
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001468 "UninstallString", uninstall_string);
1469 return lRet;
1470}
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001471#endif /* WIN3264 */
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001472
Bram Moolenaar071d4272004-06-13 20:20:40 +00001473/*
1474 * Add some entries to the registry:
1475 * - to add "Edit with Vim" to the context * menu
1476 * - to add Vim to the "Open with..." list
1477 * - to uninstall Vim
1478 */
1479/*ARGSUSED*/
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001480 static int
Bram Moolenaar071d4272004-06-13 20:20:40 +00001481install_registry(void)
1482{
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001483#ifdef WIN3264
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001484 LONG lRet = ERROR_SUCCESS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001485 const char *vim_ext_ThreadingModel = "Apartment";
1486 const char *vim_ext_name = "Vim Shell Extension";
1487 const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001488 char vim_exe_path[BUFSIZE];
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001489 char display_name[BUFSIZE];
1490 char uninstall_string[BUFSIZE];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001491
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001492 sprintf(vim_exe_path, "%s\\gvim.exe", installdir);
1493
1494 if (install_popup)
1495 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001496 char bufg[BUFSIZE];
1497 struct stat st;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001498
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001499 if (stat("gvimext.dll", &st) >= 0)
1500 sprintf(bufg, "%s\\gvimext.dll", installdir);
1501 else
1502 /* gvimext.dll is in gvimext subdir */
1503 sprintf(bufg, "%s\\gvimext\\gvimext.dll", installdir);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001504
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001505 printf("Creating \"Edit with Vim\" popup menu entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001506
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001507 lRet = register_inproc_server(
1508 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name,
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001509 bufg, vim_ext_ThreadingModel);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001510 if (ERROR_SUCCESS != lRet)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001511 return FAIL;
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001512 lRet = register_shellex(
1513 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name, vim_exe_path);
1514 if (ERROR_SUCCESS != lRet)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001515 return FAIL;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001516 }
1517
1518 if (install_openwith)
1519 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001520 printf("Creating \"Open with ...\" list entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001521
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001522 lRet = register_openwith(HKEY_CLASSES_ROOT, 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 printf("Creating an uninstall entry\n");
1528
1529 /* For the NSIS installer use the generated uninstaller. */
1530 if (interactive)
1531 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001532 sprintf(display_name, "Vim " VIM_VERSION_SHORT);
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001533 sprintf(uninstall_string, "%s\\uninstal.exe", installdir);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001534 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001535 else
1536 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001537 sprintf(display_name, "Vim " VIM_VERSION_SHORT " (self-installing)");
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001538 sprintf(uninstall_string, "%s\\uninstall-gui.exe", installdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001539 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001540
1541 lRet = register_uninstall(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001542 HKEY_LOCAL_MACHINE,
1543 "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT,
1544 display_name,
1545 uninstall_string);
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001546 if (ERROR_SUCCESS != lRet)
1547 return FAIL;
1548#endif /* WIN3264 */
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001549
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001550 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001551}
1552
1553 static void
1554change_popup_choice(int idx)
1555{
1556 if (install_popup == 0)
1557 {
1558 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";
1559 install_popup = 1;
1560 }
1561 else
1562 {
1563 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";
1564 install_popup = 0;
1565 }
1566}
1567
1568/*
1569 * Only add the choice for the popup menu entry when gvim.exe was found and
1570 * both gvimext.dll and regedit.exe exist.
1571 */
1572 static void
1573init_popup_choice(void)
1574{
1575 struct stat st;
1576
1577 if (has_gvim
1578 && (stat("gvimext.dll", &st) >= 0
1579 || stat("gvimext/gvimext.dll", &st) >= 0)
1580#ifndef WIN3264
1581 && searchpath("regedit.exe") != NULL
1582#endif
1583 )
1584 {
1585 choices[choice_count].changefunc = change_popup_choice;
1586 choices[choice_count].installfunc = NULL;
1587 choices[choice_count].active = 1;
1588 change_popup_choice(choice_count); /* set the text */
1589 ++choice_count;
1590 }
1591 else
1592 add_dummy_choice();
1593}
1594
1595 static void
1596change_openwith_choice(int idx)
1597{
1598 if (install_openwith == 0)
1599 {
1600 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";
1601 install_openwith = 1;
1602 }
1603 else
1604 {
1605 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";
1606 install_openwith = 0;
1607 }
1608}
1609
1610/*
1611 * Only add the choice for the open-with menu entry when gvim.exe was found
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001612 * and regedit.exe exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001613 */
1614 static void
1615init_openwith_choice(void)
1616{
1617 if (has_gvim
1618#ifndef WIN3264
1619 && searchpath("regedit.exe") != NULL
1620#endif
1621 )
1622 {
1623 choices[choice_count].changefunc = change_openwith_choice;
1624 choices[choice_count].installfunc = NULL;
1625 choices[choice_count].active = 1;
1626 change_openwith_choice(choice_count); /* set the text */
1627 ++choice_count;
1628 }
1629 else
1630 add_dummy_choice();
1631}
1632
1633#ifdef WIN3264
1634/* create_shortcut
1635 *
1636 * Create a shell link.
1637 *
1638 * returns 0 on failure, non-zero on successful completion.
1639 *
1640 * NOTE: Currently untested with mingw.
1641 */
1642 int
1643create_shortcut(
1644 const char *shortcut_name,
1645 const char *iconfile_path,
1646 int iconindex,
1647 const char *shortcut_target,
1648 const char *shortcut_args,
1649 const char *workingdir
1650 )
1651{
1652 IShellLink *shelllink_ptr;
1653 HRESULT hres;
1654 IPersistFile *persistfile_ptr;
1655
1656 /* Initialize COM library */
1657 hres = CoInitialize(NULL);
1658 if (!SUCCEEDED(hres))
1659 {
1660 printf("Error: Could not open the COM library. Not creating shortcut.\n");
1661 return FAIL;
1662 }
1663
1664 /* Instantiate a COM object for the ShellLink, store a pointer to it
1665 * in shelllink_ptr. */
1666 hres = CoCreateInstance(&CLSID_ShellLink,
1667 NULL,
1668 CLSCTX_INPROC_SERVER,
1669 &IID_IShellLink,
1670 (void **) &shelllink_ptr);
1671
1672 if (SUCCEEDED(hres)) /* If the instantiation was successful... */
1673 {
1674 /* ...Then build a PersistFile interface for the ShellLink so we can
1675 * save it as a file after we build it. */
1676 hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
1677 &IID_IPersistFile, (void **) &persistfile_ptr);
1678
1679 if (SUCCEEDED(hres))
1680 {
1681 wchar_t wsz[BUFSIZE];
1682
1683 /* translate the (possibly) multibyte shortcut filename to windows
1684 * Unicode so it can be used as a file name.
1685 */
1686 MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
1687
1688 /* set the attributes */
1689 shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
1690 shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
1691 workingdir);
1692 shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
1693 iconfile_path, iconindex);
1694 shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
1695
1696 /* save the shortcut to a file and return the PersistFile object*/
1697 persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
1698 persistfile_ptr->lpVtbl->Release(persistfile_ptr);
1699 }
1700 else
1701 {
1702 printf("QueryInterface Error\n");
1703 return FAIL;
1704 }
1705
1706 /* Return the ShellLink object */
1707 shelllink_ptr->lpVtbl->Release(shelllink_ptr);
1708 }
1709 else
1710 {
1711 printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
1712 return FAIL;
1713 }
1714
1715 return OK;
1716}
1717
1718/*
1719 * Build a path to where we will put a specified link.
1720 *
1721 * Return 0 on error, non-zero on success
1722 */
1723 int
1724build_link_name(
1725 char *link_path,
1726 const char *link_name,
1727 const char *shell_folder_name)
1728{
1729 char shell_folder_path[BUFSIZE];
1730
1731 if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
1732 {
1733 printf("An error occurred while attempting to find the path to %s.\n",
1734 shell_folder_name);
1735 return FAIL;
1736 }
1737
1738 /* Make sure the directory exists (create Start Menu\Programs\Vim).
1739 * Ignore errors if it already exists. */
1740 vim_mkdir(shell_folder_path, 0755);
1741
1742 /* build the path to the shortcut and the path to gvim.exe */
1743 sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
1744
1745 return OK;
1746}
1747
1748 static int
1749build_shortcut(
1750 const char *name, /* Name of the shortcut */
1751 const char *exename, /* Name of the executable (e.g., vim.exe) */
1752 const char *args,
1753 const char *shell_folder,
1754 const char *workingdir)
1755{
1756 char executable_path[BUFSIZE];
1757 char link_name[BUFSIZE];
1758
1759 sprintf(executable_path, "%s\\%s", installdir, exename);
1760
1761 if (build_link_name(link_name, name, shell_folder) == FAIL)
1762 {
1763 printf("An error has occurred. A shortcut to %s will not be created %s.\n",
1764 name,
1765 *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
1766 return FAIL;
1767 }
1768
1769 /* Create the shortcut: */
1770 return create_shortcut(link_name, executable_path, 0,
1771 executable_path, args, workingdir);
1772}
1773
1774/*
1775 * We used to use "homedir" as the working directory, but that is a bad choice
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001776 * on multi-user systems. However, not specifying a directory results in the
1777 * current directory to be c:\Windows\system32 on Windows 7. Use environment
1778 * variables instead.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001779 */
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001780#define WORKDIR "%HOMEDRIVE%%HOMEPATH%"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001781
1782/*
1783 * Create shortcut(s) in the Start Menu\Programs\Vim folder.
1784 */
1785 static void
1786install_start_menu(int idx)
1787{
1788 need_uninstall_entry = 1;
1789 printf("Creating start menu\n");
1790 if (has_vim)
1791 {
1792 if (build_shortcut("Vim", "vim.exe", "",
1793 VIM_STARTMENU, WORKDIR) == FAIL)
1794 return;
1795 if (build_shortcut("Vim Read-only", "vim.exe", "-R",
1796 VIM_STARTMENU, WORKDIR) == FAIL)
1797 return;
1798 if (build_shortcut("Vim Diff", "vim.exe", "-d",
1799 VIM_STARTMENU, WORKDIR) == FAIL)
1800 return;
1801 }
1802 if (has_gvim)
1803 {
1804 if (build_shortcut("gVim", "gvim.exe", "",
1805 VIM_STARTMENU, WORKDIR) == FAIL)
1806 return;
1807 if (build_shortcut("gVim Easy", "gvim.exe", "-y",
1808 VIM_STARTMENU, WORKDIR) == FAIL)
1809 return;
1810 if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
1811 VIM_STARTMENU, WORKDIR) == FAIL)
1812 return;
1813 if (build_shortcut("gVim Diff", "gvim.exe", "-d",
1814 VIM_STARTMENU, WORKDIR) == FAIL)
1815 return;
1816 }
1817 if (build_shortcut("Uninstall",
1818 interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
1819 VIM_STARTMENU, installdir) == FAIL)
1820 return;
1821 /* For Windows NT the working dir of the vimtutor.bat must be right,
1822 * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
1823 if (build_shortcut("Vim tutor", "vimtutor.bat", "",
1824 VIM_STARTMENU, installdir) == FAIL)
1825 return;
1826 if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
1827 VIM_STARTMENU, WORKDIR) == FAIL)
1828 return;
1829 {
1830 char shell_folder_path[BUFSIZE];
1831
1832 /* Creating the URL shortcut works a bit differently... */
1833 if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
1834 {
1835 printf("Finding the path of the Start menu failed\n");
1836 return ;
1837 }
1838 add_pathsep(shell_folder_path);
1839 strcat(shell_folder_path, "Vim Online.url");
1840 if (!WritePrivateProfileString("InternetShortcut", "URL",
1841 "http://vim.sf.net/", shell_folder_path))
1842 {
1843 printf("Creating the Vim online URL failed\n");
1844 return;
1845 }
1846 }
1847}
1848
1849 static void
1850toggle_startmenu_choice(int idx)
1851{
1852 if (choices[idx].installfunc == NULL)
1853 {
1854 choices[idx].installfunc = install_start_menu;
1855 choices[idx].text = "Add Vim to the Start menu";
1856 }
1857 else
1858 {
1859 choices[idx].installfunc = NULL;
1860 choices[idx].text = "Do NOT add Vim to the Start menu";
1861 }
1862}
1863
1864/*
1865 * Function to actually create the shortcuts
1866 *
1867 * Currently I am supplying no working directory to the shortcut. This
1868 * means that the initial working dir will be:
1869 * - the location of the shortcut if no file is supplied
1870 * - the location of the file being edited if a file is supplied (ie via
1871 * drag and drop onto the shortcut).
1872 */
1873 void
1874install_shortcut_gvim(int idx)
1875{
1876 /* Create shortcut(s) on the desktop */
1877 if (choices[idx].arg)
1878 {
1879 (void)build_shortcut(icon_names[0], "gvim.exe",
1880 "", "desktop", WORKDIR);
1881 need_uninstall_entry = 1;
1882 }
1883}
1884
1885 void
1886install_shortcut_evim(int idx)
1887{
1888 if (choices[idx].arg)
1889 {
1890 (void)build_shortcut(icon_names[1], "gvim.exe",
1891 "-y", "desktop", WORKDIR);
1892 need_uninstall_entry = 1;
1893 }
1894}
1895
1896 void
1897install_shortcut_gview(int idx)
1898{
1899 if (choices[idx].arg)
1900 {
1901 (void)build_shortcut(icon_names[2], "gvim.exe",
1902 "-R", "desktop", WORKDIR);
1903 need_uninstall_entry = 1;
1904 }
1905}
1906
1907 void
1908toggle_shortcut_choice(int idx)
1909{
1910 char *arg;
1911
1912 if (choices[idx].installfunc == install_shortcut_gvim)
1913 arg = "gVim";
1914 else if (choices[idx].installfunc == install_shortcut_evim)
1915 arg = "gVim Easy";
1916 else
1917 arg = "gVim Read-only";
1918 if (choices[idx].arg)
1919 {
1920 choices[idx].arg = 0;
1921 alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
1922 }
1923 else
1924 {
1925 choices[idx].arg = 1;
1926 alloc_text(idx, "Create a desktop icon for %s", arg);
1927 }
1928}
1929#endif /* WIN3264 */
1930
1931 static void
1932init_startmenu_choice(void)
1933{
1934#ifdef WIN3264
1935 /* Start menu */
1936 choices[choice_count].changefunc = toggle_startmenu_choice;
1937 choices[choice_count].installfunc = NULL;
1938 choices[choice_count].active = 1;
1939 toggle_startmenu_choice(choice_count); /* set the text */
1940 ++choice_count;
1941#else
1942 add_dummy_choice();
1943#endif
1944}
1945
1946/*
1947 * Add the choice for the desktop shortcuts.
1948 */
1949 static void
1950init_shortcut_choices(void)
1951{
1952#ifdef WIN3264
1953 /* Shortcut to gvim */
1954 choices[choice_count].text = NULL;
1955 choices[choice_count].arg = 0;
1956 choices[choice_count].active = has_gvim;
1957 choices[choice_count].changefunc = toggle_shortcut_choice;
1958 choices[choice_count].installfunc = install_shortcut_gvim;
1959 toggle_shortcut_choice(choice_count);
1960 ++choice_count;
1961
1962 /* Shortcut to evim */
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_evim;
1968 toggle_shortcut_choice(choice_count);
1969 ++choice_count;
1970
1971 /* Shortcut to gview */
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_gview;
1977 toggle_shortcut_choice(choice_count);
1978 ++choice_count;
1979#else
1980 add_dummy_choice();
1981 add_dummy_choice();
1982 add_dummy_choice();
1983#endif
1984}
1985
1986#ifdef WIN3264
1987/*
1988 * Attempt to register OLE for Vim.
1989 */
1990 static void
1991install_OLE_register(void)
1992{
1993 char register_command_string[BUFSIZE + 30];
1994
1995 printf("\n--- Attempting to register Vim with OLE ---\n");
1996 printf("(There is no message whether this works or not.)\n");
1997
1998#ifndef __CYGWIN__
1999 sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
2000#else
2001 /* handle this differently for Cygwin which sometimes has trouble with
2002 * Windows-style pathnames here. */
2003 sprintf(register_command_string, "./gvim.exe -silent -register");
2004#endif
2005 system(register_command_string);
2006}
2007#endif /* WIN3264 */
2008
2009/*
2010 * Remove the last part of directory "path[]" to get its parent, and put the
2011 * result in "to[]".
2012 */
2013 static void
2014dir_remove_last(const char *path, char to[BUFSIZE])
2015{
2016 char c;
2017 long last_char_to_copy;
2018 long path_length = strlen(path);
2019
2020 /* skip the last character just in case it is a '\\' */
2021 last_char_to_copy = path_length - 2;
2022 c = path[last_char_to_copy];
2023
2024 while (c != '\\')
2025 {
2026 last_char_to_copy--;
2027 c = path[last_char_to_copy];
2028 }
2029
2030 strncpy(to, path, (size_t)last_char_to_copy);
2031 to[last_char_to_copy] = NUL;
2032}
2033
2034 static void
2035set_directories_text(int idx)
2036{
2037 if (vimfiles_dir_choice == (int)vimfiles_dir_none)
2038 alloc_text(idx, "Do NOT create plugin directories%s", "");
2039 else
2040 alloc_text(idx, "Create plugin directories: %s",
2041 vimfiles_dir_choices[vimfiles_dir_choice]);
2042}
2043
2044/*
2045 * Change the directory that the vim plugin directories will be created in:
2046 * $HOME, $VIM or nowhere.
2047 */
2048 static void
2049change_directories_choice(int idx)
2050{
2051 int choice_count = TABLE_SIZE(vimfiles_dir_choices);
2052
2053 /* Don't offer the $HOME choice if $HOME isn't set. */
2054 if (getenv("HOME") == NULL)
2055 --choice_count;
2056 vimfiles_dir_choice = get_choice(vimfiles_dir_choices, choice_count);
2057 set_directories_text(idx);
2058}
2059
2060/*
2061 * Create the plugin directories...
2062 */
2063/*ARGSUSED*/
2064 static void
2065install_vimfilesdir(int idx)
2066{
2067 int i;
2068 char *p;
2069 char vimdir_path[BUFSIZE];
2070 char vimfiles_path[BUFSIZE];
2071 char tmp_dirname[BUFSIZE];
2072
2073 /* switch on the location that the user wants the plugin directories
2074 * built in */
2075 switch (vimfiles_dir_choice)
2076 {
2077 case vimfiles_dir_vim:
2078 {
2079 /* Go to the %VIM% directory - check env first, then go one dir
2080 * below installdir if there is no %VIM% environment variable.
2081 * The accuracy of $VIM is checked in inspect_system(), so we
2082 * can be sure it is ok to use here. */
2083 p = getenv("VIM");
2084 if (p == NULL) /* No $VIM in path */
2085 dir_remove_last(installdir, vimdir_path);
2086 else
2087 strcpy(vimdir_path, p);
2088 break;
2089 }
2090 case vimfiles_dir_home:
2091 {
2092 /* Find the $HOME directory. Its existence was already checked. */
2093 p = getenv("HOME");
2094 if (p == NULL)
2095 {
2096 printf("Internal error: $HOME is NULL\n");
2097 p = "c:\\";
2098 }
2099 strcpy(vimdir_path, p);
2100 break;
2101 }
2102 case vimfiles_dir_none:
2103 {
2104 /* Do not create vim plugin directory */
2105 return;
2106 }
2107 }
2108
2109 /* Now, just create the directory. If it already exists, it will fail
2110 * silently. */
2111 sprintf(vimfiles_path, "%s\\vimfiles", vimdir_path);
2112 vim_mkdir(vimfiles_path, 0755);
2113
2114 printf("Creating the following directories in \"%s\":\n", vimfiles_path);
2115 for (i = 0; i < TABLE_SIZE(vimfiles_subdirs); i++)
2116 {
2117 sprintf(tmp_dirname, "%s\\%s", vimfiles_path, vimfiles_subdirs[i]);
2118 printf(" %s", vimfiles_subdirs[i]);
2119 vim_mkdir(tmp_dirname, 0755);
2120 }
2121 printf("\n");
2122}
2123
2124/*
2125 * Add the creation of runtime files to the setup sequence.
2126 */
2127 static void
2128init_directories_choice(void)
2129{
2130 struct stat st;
2131 char tmp_dirname[BUFSIZE];
2132 char *p;
2133
2134 choices[choice_count].text = alloc(150);
2135 choices[choice_count].changefunc = change_directories_choice;
2136 choices[choice_count].installfunc = install_vimfilesdir;
2137 choices[choice_count].active = 1;
2138
2139 /* Check if the "compiler" directory already exists. That's a good
2140 * indication that the plugin directories were already created. */
2141 if (getenv("HOME") != NULL)
2142 {
2143 vimfiles_dir_choice = (int)vimfiles_dir_home;
2144 sprintf(tmp_dirname, "%s\\vimfiles\\compiler", getenv("HOME"));
2145 if (stat(tmp_dirname, &st) == 0)
2146 vimfiles_dir_choice = (int)vimfiles_dir_none;
2147 }
2148 else
2149 {
2150 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2151 p = getenv("VIM");
2152 if (p == NULL) /* No $VIM in path, use the install dir */
2153 dir_remove_last(installdir, tmp_dirname);
2154 else
2155 strcpy(tmp_dirname, p);
2156 strcat(tmp_dirname, "\\vimfiles\\compiler");
2157 if (stat(tmp_dirname, &st) == 0)
2158 vimfiles_dir_choice = (int)vimfiles_dir_none;
2159 }
2160
2161 set_directories_text(choice_count);
2162 ++choice_count;
2163}
2164
2165/*
2166 * Setup the choices and the default values.
2167 */
2168 static void
2169setup_choices(void)
2170{
2171 /* install the batch files */
2172 init_bat_choices();
2173
2174 /* (over) write _vimrc file */
2175 init_vimrc_choices();
2176
2177 /* Whether to add Vim to the popup menu */
2178 init_popup_choice();
2179
2180 /* Whether to add Vim to the "Open With..." menu */
2181 init_openwith_choice();
2182
2183 /* Whether to add Vim to the Start Menu. */
2184 init_startmenu_choice();
2185
2186 /* Whether to add shortcuts to the Desktop. */
2187 init_shortcut_choices();
2188
2189 /* Whether to create the runtime directories. */
2190 init_directories_choice();
2191}
2192
2193 static void
2194print_cmd_line_help(void)
2195{
2196 printf("Vim installer non-interactive command line arguments:\n");
2197 printf("\n");
2198 printf("-create-batfiles [vim gvim evim view gview vimdiff gvimdiff]\n");
2199 printf(" Create .bat files for Vim variants in the Windows directory.\n");
2200 printf("-create-vimrc\n");
2201 printf(" Create a default _vimrc file if one does not already exist.\n");
2202 printf("-install-popup\n");
2203 printf(" Install the Edit-with-Vim context menu entry\n");
2204 printf("-install-openwith\n");
2205 printf(" Add Vim to the \"Open With...\" context menu list\n");
2206#ifdef WIN3264
2207 printf("-add-start-menu");
2208 printf(" Add Vim to the start menu\n");
2209 printf("-install-icons");
2210 printf(" Create icons for gVim executables on the desktop\n");
2211#endif
2212 printf("-create-directories [vim|home]\n");
2213 printf(" Create runtime directories to drop plugins into; in the $VIM\n");
2214 printf(" or $HOME directory\n");
2215#ifdef WIN3264
2216 printf("-register-OLE");
Bram Moolenaarce0842a2005-07-18 21:58:11 +00002217 printf(" Ignored\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002218#endif
2219 printf("\n");
2220}
2221
2222/*
2223 * Setup installation choices based on command line switches
2224 */
2225 static void
2226command_line_setup_choices(int argc, char **argv)
2227{
2228 int i, j;
2229
2230 for (i = 1; i < argc; i++)
2231 {
2232 if (strcmp(argv[i], "-create-batfiles") == 0)
2233 {
2234 if (i + 1 == argc)
2235 continue;
2236 while (argv[i + 1][0] != '-' && i < argc)
2237 {
2238 i++;
2239 for (j = 1; j < TARGET_COUNT; ++j)
2240 if ((targets[j].exenamearg[0] == 'g' ? has_gvim : has_vim)
2241 && strcmp(argv[i], targets[j].name) == 0)
2242 {
2243 init_bat_choice(j);
2244 break;
2245 }
2246 if (j == TARGET_COUNT)
2247 printf("%s is not a valid choice for -create-batfiles\n",
2248 argv[i]);
2249
2250 if (i + 1 == argc)
2251 break;
2252 }
2253 }
2254 else if (strcmp(argv[i], "-create-vimrc") == 0)
2255 {
2256 /* Setup default vimrc choices. If there is already a _vimrc file,
2257 * it will NOT be overwritten.
2258 */
2259 init_vimrc_choices();
2260 }
2261 else if (strcmp(argv[i], "-install-popup") == 0)
2262 {
2263 init_popup_choice();
2264 }
2265 else if (strcmp(argv[i], "-install-openwith") == 0)
2266 {
2267 init_openwith_choice();
2268 }
2269 else if (strcmp(argv[i], "-add-start-menu") == 0)
2270 {
2271 init_startmenu_choice();
2272 }
2273 else if (strcmp(argv[i], "-install-icons") == 0)
2274 {
2275 init_shortcut_choices();
2276 }
2277 else if (strcmp(argv[i], "-create-directories") == 0)
2278 {
2279 init_directories_choice();
2280 if (argv[i + 1][0] != '-')
2281 {
2282 i++;
2283 if (strcmp(argv[i], "vim") == 0)
2284 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2285 else if (strcmp(argv[i], "home") == 0)
2286 {
2287 if (getenv("HOME") == NULL) /* No $HOME in environment */
2288 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2289 else
2290 vimfiles_dir_choice = (int)vimfiles_dir_home;
2291 }
2292 else
2293 {
2294 printf("Unknown argument for -create-directories: %s\n",
2295 argv[i]);
2296 print_cmd_line_help();
2297 }
2298 }
2299 else /* No choice specified, default to vim directory */
2300 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2301 }
2302#ifdef WIN3264
2303 else if (strcmp(argv[i], "-register-OLE") == 0)
2304 {
2305 /* This is always done when gvim is found */
2306 }
2307#endif
2308 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
2465#ifdef WIN3264
2466 /* Register gvim with OLE. */
2467 if (has_gvim)
2468 install_OLE_register();
2469#endif
2470}
2471
2472/*
2473 * request_choice
2474 */
2475 static void
2476request_choice(void)
2477{
2478 int i;
2479
2480 printf("\n\nInstall will do for you:\n");
2481 for (i = 0; i < choice_count; ++i)
2482 if (choices[i].active)
2483 printf("%2d %s\n", i + 1, choices[i].text);
2484 printf("To change an item, enter its number\n\n");
2485 printf("Enter item number, h (help), d (do it) or q (quit): ");
2486}
2487
2488 int
2489main(int argc, char **argv)
2490{
2491 int i;
2492 char buf[BUFSIZE];
2493
2494 /*
2495 * Run interactively if there are no command line arguments.
2496 */
2497 if (argc > 1)
2498 interactive = 0;
2499 else
2500 interactive = 1;
2501
2502 /* Initialize this program. */
2503 do_inits(argv);
2504
2505#ifdef WIN3264
2506 if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
2507 {
2508 /* Only check for already installed Vims. Used by NSIS installer. */
Bram Moolenaar442b4222010-05-24 21:34:22 +02002509 i = uninstall_check(1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002510
2511 /* Find the value of $VIM, because NSIS isn't able to do this by
2512 * itself. */
2513 get_vim_env();
2514
2515 /* When nothing found exit quietly. If something found wait for
Bram Moolenaarb230bd52010-05-25 21:02:00 +02002516 * a little while, so that the user can read the messages. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002517 if (i)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002518 sleep(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519 exit(0);
2520 }
2521#endif
2522
2523 printf("This program sets up the installation of Vim "
2524 VIM_VERSION_MEDIUM "\n\n");
2525
2526 /* Check if the user unpacked the archives properly. */
2527 check_unpack();
2528
2529#ifdef WIN3264
2530 /* Check for already installed Vims. */
2531 if (interactive)
Bram Moolenaar442b4222010-05-24 21:34:22 +02002532 uninstall_check(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002533#endif
2534
2535 /* Find out information about the system. */
2536 inspect_system();
2537
2538 if (interactive)
2539 {
2540 /* Setup all the choices. */
2541 setup_choices();
2542
2543 /* Let the user change choices and finally install (or quit). */
2544 for (;;)
2545 {
2546 request_choice();
2547 rewind(stdin);
2548 if (scanf("%99s", buf) == 1)
2549 {
2550 if (isdigit(buf[0]))
2551 {
2552 /* Change a choice. */
2553 i = atoi(buf);
2554 if (i > 0 && i <= choice_count && choices[i - 1].active)
2555 (choices[i - 1].changefunc)(i - 1);
2556 else
2557 printf("\nIllegal choice\n");
2558 }
2559 else if (buf[0] == 'h' || buf[0] == 'H')
2560 {
2561 /* Help */
2562 show_help();
2563 }
2564 else if (buf[0] == 'd' || buf[0] == 'D')
2565 {
2566 /* Install! */
2567 install();
2568 printf("\nThat finishes the installation. Happy Vimming!\n");
2569 break;
2570 }
2571 else if (buf[0] == 'q' || buf[0] == 'Q')
2572 {
2573 /* Quit */
2574 printf("\nExiting without anything done\n");
2575 break;
2576 }
2577 else
2578 printf("\nIllegal choice\n");
2579 }
2580 }
2581 printf("\n");
Bram Moolenaar442b4222010-05-24 21:34:22 +02002582 myexit(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002583 }
2584 else
2585 {
2586 /*
2587 * Run non-interactive - setup according to the command line switches
2588 */
2589 command_line_setup_choices(argc, argv);
2590 install();
Bram Moolenaar442b4222010-05-24 21:34:22 +02002591
2592 /* Avoid that the user has to hit Enter, just wait a little bit to
2593 * allow reading the messages. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002594 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002595 }
2596
Bram Moolenaar071d4272004-06-13 20:20:40 +00002597 return 0;
2598}