Merge branch 'vim-with-runtime' into feat/code-check
[vim_extended.git] / src / dosinst.c
blobc4ed7f6a118540dd055b479d7f139f7574f723cb
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
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 */
11 * dosinst.c: Install program for Vim on MS-DOS and MS-Windows
13 * Compile with Make_mvc.mak, Make_bc3.mak, Make_bc5.mak or Make_djg.mak.
17 * Include common code for dosinst.c and uninstal.c.
19 #define DOSINST
20 #include "dosinst.h"
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; }
25 int has_vim = 0; /* installable vim.exe exists */
26 int has_gvim = 0; /* installable gvim.exe exists */
28 char oldvimrc[BUFSIZE]; /* name of existing vimrc file */
29 char vimrc[BUFSIZE]; /* name of vimrc file to create */
31 char *default_bat_dir = NULL; /* when not NULL, use this as the default
32 directory to write .bat files in */
33 char *default_vim_dir = NULL; /* when not NULL, use this as the default
34 install dir for NSIS */
35 #if 0
36 char homedir[BUFSIZE]; /* home directory or "" */
37 #endif
40 * Structure used for each choice the user can make.
42 struct choice
44 int active; /* non-zero when choice is active */
45 char *text; /* text displayed for this choice */
46 void (*changefunc)(int idx); /* function to change this choice */
47 int arg; /* argument for function */
48 void (*installfunc)(int idx); /* function to install this choice */
51 struct choice choices[30]; /* choices the user can make */
52 int choice_count = 0; /* number of choices available */
54 #define TABLE_SIZE(s) (int)(sizeof(s) / sizeof(*s))
56 enum
58 compat_vi = 1,
59 compat_some_enhancements,
60 compat_all_enhancements
62 char *(compat_choices[]) =
64 "\nChoose the default way to run Vim:",
65 "Vi compatible",
66 "with some Vim ehancements",
67 "with syntax highlighting and other features switched on",
69 int compat_choice = (int)compat_all_enhancements;
70 char *compat_text = "- run Vim %s";
72 enum
74 remap_no = 1,
75 remap_win
77 char *(remap_choices[]) =
79 "\nChoose:",
80 "Do not remap keys for Windows behavior",
81 "Remap a few keys for Windows behavior (<C-V>, <C-C>, etc)",
83 int remap_choice = (int)remap_win;
84 char *remap_text = "- %s";
86 enum
88 mouse_xterm = 1,
89 mouse_mswin
91 char *(mouse_choices[]) =
93 "\nChoose the way how Vim uses the mouse:",
94 "right button extends selection (the Unix way)",
95 "right button has a popup menu (the Windows way)",
97 int mouse_choice = (int)mouse_mswin;
98 char *mouse_text = "- The mouse %s";
100 enum
102 vimfiles_dir_none = 1,
103 vimfiles_dir_vim,
104 vimfiles_dir_home
106 static char *(vimfiles_dir_choices[]) =
108 "\nCreate plugin directories:",
109 "No",
110 "In the VIM directory",
111 "In your HOME directory",
113 static int vimfiles_dir_choice;
115 /* non-zero when selected to install the popup menu entry. */
116 static int install_popup = 0;
118 /* non-zero when selected to install the "Open with" entry. */
119 static int install_openwith = 0;
121 /* non-zero when need to add an uninstall entry in the registry */
122 static int need_uninstall_entry = 0;
125 * Definitions of the directory name (under $VIM) of the vimfiles directory
126 * and its subdirectories:
128 static char *(vimfiles_subdirs[]) =
130 "colors",
131 "compiler",
132 "doc",
133 "ftdetect",
134 "ftplugin",
135 "indent",
136 "keymap",
137 "plugin",
138 "syntax",
142 * Copy a directory name from "dir" to "buf", doubling backslashes.
143 * Also make sure it ends in a double backslash.
145 static void
146 double_bs(char *dir, char *buf)
148 char *d = buf;
149 char *s;
151 for (s = dir; *s; ++s)
153 if (*s == '\\')
154 *d++ = '\\';
155 *d++ = *s;
157 /* when dir is not empty, it must end in a double backslash */
158 if (d > buf && d[-1] != '\\')
160 *d++ = '\\';
161 *d++ = '\\';
163 *d = NUL;
167 * Obtain a choice from a table.
168 * First entry is a question, others are choices.
170 static int
171 get_choice(char **table, int entries)
173 int answer;
174 int idx;
175 char dummy[100];
179 for (idx = 0; idx < entries; ++idx)
181 if (idx)
182 printf("%2d ", idx);
183 printf(table[idx]);
184 printf("\n");
186 printf("Choice: ");
187 if (scanf("%d", &answer) != 1)
189 scanf("%99s", dummy);
190 answer = 0;
193 while (answer < 1 || answer >= entries);
195 return answer;
199 * Check if the user unpacked the archives properly.
200 * Sets "runtimeidx".
202 static void
203 check_unpack(void)
205 char buf[BUFSIZE];
206 FILE *fd;
207 struct stat st;
209 /* check for presence of the correct version number in installdir[] */
210 runtimeidx = strlen(installdir) - strlen(VIM_VERSION_NODOT);
211 if (runtimeidx <= 0
212 || stricmp(installdir + runtimeidx, VIM_VERSION_NODOT) != 0
213 || (installdir[runtimeidx - 1] != '/'
214 && installdir[runtimeidx - 1] != '\\'))
216 printf("ERROR: Install program not in directory \"%s\"\n",
217 VIM_VERSION_NODOT);
218 printf("This program can only work when it is located in its original directory\n");
219 myexit(1);
222 /* check if filetype.vim is present, which means the runtime archive has
223 * been unpacked */
224 sprintf(buf, "%s\\filetype.vim", installdir);
225 if (stat(buf, &st) < 0)
227 printf("ERROR: Cannot find filetype.vim in \"%s\"\n", installdir);
228 printf("It looks like you did not unpack the runtime archive.\n");
229 printf("You must unpack the runtime archive \"vim%srt.zip\" before installing.\n",
230 VIM_VERSION_NODOT + 3);
231 myexit(1);
234 /* Check if vim.exe or gvim.exe is in the current directory. */
235 if ((fd = fopen("gvim.exe", "r")) != NULL)
237 fclose(fd);
238 has_gvim = 1;
240 if ((fd = fopen("vim.exe", "r")) != NULL)
242 fclose(fd);
243 has_vim = 1;
245 if (!has_gvim && !has_vim)
247 printf("ERROR: Cannot find any Vim executables in \"%s\"\n\n",
248 installdir);
249 myexit(1);
254 * Compare paths "p[plen]" to "q[qlen]". Return 0 if they match.
255 * Ignores case and differences between '/' and '\'.
256 * "plen" and "qlen" can be negative, strlen() is used then.
258 static int
259 pathcmp(char *p, int plen, char *q, int qlen)
261 int i;
263 if (plen < 0)
264 plen = strlen(p);
265 if (qlen < 0)
266 qlen = strlen(q);
267 for (i = 0; ; ++i)
269 /* End of "p": check if "q" also ends or just has a slash. */
270 if (i == plen)
272 if (i == qlen) /* match */
273 return 0;
274 if (i == qlen - 1 && (q[i] == '\\' || q[i] == '/'))
275 return 0; /* match with trailing slash */
276 return 1; /* no match */
279 /* End of "q": check if "p" also ends or just has a slash. */
280 if (i == qlen)
282 if (i == plen) /* match */
283 return 0;
284 if (i == plen - 1 && (p[i] == '\\' || p[i] == '/'))
285 return 0; /* match with trailing slash */
286 return 1; /* no match */
289 if (!(mytoupper(p[i]) == mytoupper(q[i])
290 || ((p[i] == '/' || p[i] == '\\')
291 && (q[i] == '/' || q[i] == '\\'))))
292 return 1; /* no match */
294 /*NOTREACHED*/
298 * If the executable "**destination" is in the install directory, find another
299 * one in $PATH.
300 * On input "**destination" is the path of an executable in allocated memory
301 * (or NULL).
302 * "*destination" is set to NULL or the location of the file.
304 static void
305 findoldfile(char **destination)
307 char *bp = *destination;
308 size_t indir_l = strlen(installdir);
309 char *cp = bp + indir_l;
310 char *tmpname;
311 char *farname;
314 * No action needed if exe not found or not in this directory.
316 if (bp == NULL
317 || strnicmp(bp, installdir, indir_l) != 0
318 || strchr("/\\", *cp++) == NULL
319 || strchr(cp, '\\') != NULL
320 || strchr(cp, '/') != NULL)
321 return;
323 tmpname = alloc((int)strlen(cp) + 1);
324 strcpy(tmpname, cp);
325 tmpname[strlen(tmpname) - 1] = 'x'; /* .exe -> .exx */
327 if (access(tmpname, 0) == 0)
329 printf("\nERROR: %s and %s clash. Remove or rename %s.\n",
330 tmpname, cp, tmpname);
331 myexit(1);
334 if (rename(cp, tmpname) != 0)
336 printf("\nERROR: failed to rename %s to %s: %s\n",
337 cp, tmpname, strerror(0));
338 myexit(1);
341 farname = searchpath_save(cp);
343 if (rename(tmpname, cp) != 0)
345 printf("\nERROR: failed to rename %s back to %s: %s\n",
346 tmpname, cp, strerror(0));
347 myexit(1);
350 free(*destination);
351 free(tmpname);
352 *destination = farname;
356 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
357 * When "check_bat_only" is TRUE, only find "default_bat_dir".
359 static void
360 find_bat_exe(int check_bat_only)
362 int i;
364 /* avoid looking in the "installdir" by chdir to system root */
365 mch_chdir(sysdrive);
366 mch_chdir("\\");
368 for (i = 1; i < TARGET_COUNT; ++i)
370 targets[i].oldbat = searchpath_save(targets[i].batname);
371 if (!check_bat_only)
372 targets[i].oldexe = searchpath_save(targets[i].exename);
374 if (default_bat_dir == NULL && targets[i].oldbat != NULL)
376 default_bat_dir = alloc(strlen(targets[i].oldbat) + 1);
377 strcpy(default_bat_dir, targets[i].oldbat);
378 remove_tail(default_bat_dir);
380 if (check_bat_only && targets[i].oldbat != NULL)
382 free(targets[i].oldbat);
383 targets[i].oldbat = NULL;
387 mch_chdir(installdir);
390 #ifdef WIN3264
392 * Get the value of $VIMRUNTIME or $VIM and write it in $TEMP/vimini.ini, so
393 * that NSIS can read it.
394 * When not set, use the directory of a previously installed Vim.
396 static void
397 get_vim_env(void)
399 char *vim;
400 char buf[BUFSIZE];
401 FILE *fd;
402 char fname[BUFSIZE];
404 /* First get $VIMRUNTIME. If it's set, remove the tail. */
405 vim = getenv("VIMRUNTIME");
406 if (vim != NULL && *vim != 0)
408 strcpy(buf, vim);
409 remove_tail(buf);
410 vim = buf;
412 else
414 vim = getenv("VIM");
415 if (vim == NULL || *vim == 0)
417 /* Use the directory from an old uninstall entry. */
418 if (default_vim_dir != NULL)
419 vim = default_vim_dir;
420 else
421 /* Let NSIS know there is no default, it should use
422 * $PROGRAMFILES. */
423 vim = "";
427 /* NSIS also uses GetTempPath(), thus we should get the same directory
428 * name as where NSIS will look for vimini.ini. */
429 GetTempPath(BUFSIZE, fname);
430 add_pathsep(fname);
431 strcat(fname, "vimini.ini");
433 fd = fopen(fname, "w");
434 if (fd != NULL)
436 /* Make it look like an .ini file, so that NSIS can read it with a
437 * ReadINIStr command. */
438 fprintf(fd, "[vimini]\n");
439 fprintf(fd, "dir=\"%s\"\n", vim);
440 fclose(fd);
442 else
444 printf("Failed to open %s\n", fname);
445 Sleep(2000);
450 * Check for already installed Vims.
451 * Return non-zero when found one.
453 static int
454 uninstall_check(void)
456 HKEY key_handle;
457 HKEY uninstall_key_handle;
458 char *uninstall_key = "software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
459 char subkey_name_buff[BUFSIZE];
460 char temp_string_buffer[BUFSIZE];
461 DWORD local_bufsize = BUFSIZE;
462 FILETIME temp_pfiletime;
463 DWORD key_index;
464 char input;
465 long code;
466 DWORD value_type;
467 DWORD orig_num_keys;
468 DWORD new_num_keys;
469 int foundone = 0;
471 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0, KEY_READ,
472 &key_handle);
473 CHECK_REG_ERROR(code);
475 for (key_index = 0;
476 RegEnumKeyEx(key_handle, key_index, subkey_name_buff, &local_bufsize,
477 NULL, NULL, NULL, &temp_pfiletime) != ERROR_NO_MORE_ITEMS;
478 key_index++)
480 local_bufsize = BUFSIZE;
481 if (strncmp("Vim", subkey_name_buff, 3) == 0)
483 /* Open the key named Vim* */
484 code = RegOpenKeyEx(key_handle, subkey_name_buff, 0, KEY_READ,
485 &uninstall_key_handle);
486 CHECK_REG_ERROR(code);
488 /* get the DisplayName out of it to show the user */
489 code = RegQueryValueEx(uninstall_key_handle, "displayname", 0,
490 &value_type, (LPBYTE)temp_string_buffer,
491 &local_bufsize);
492 local_bufsize = BUFSIZE;
493 CHECK_REG_ERROR(code);
495 foundone = 1;
496 printf("\n*********************************************************\n");
497 printf("Vim Install found what looks like an existing Vim version.\n");
498 printf("The name of the entry is:\n");
499 printf("\n \"%s\"\n\n", temp_string_buffer);
501 printf("Installing the new version will disable part of the existing version.\n");
502 printf("(The batch files used in a console and the \"Edit with Vim\" entry in\n");
503 printf("the popup menu will use the new version)\n");
505 printf("\nDo you want to uninstall \"%s\" now?\n(y)es/(n)o) ", temp_string_buffer);
506 fflush(stdout);
508 /* get the UninstallString */
509 code = RegQueryValueEx(uninstall_key_handle, "uninstallstring", 0,
510 &value_type, (LPBYTE)temp_string_buffer, &local_bufsize);
511 local_bufsize = BUFSIZE;
512 CHECK_REG_ERROR(code);
514 /* Remember the directory, it is used as the default for NSIS. */
515 default_vim_dir = alloc(strlen(temp_string_buffer) + 1);
516 strcpy(default_vim_dir, temp_string_buffer);
517 remove_tail(default_vim_dir);
518 remove_tail(default_vim_dir);
520 input = 'n';
523 if (input != 'n')
524 printf("%c is an invalid reply. Please enter either 'y' or 'n'\n", input);
526 rewind(stdin);
527 scanf("%c", &input);
528 switch (input)
530 case 'y':
531 case 'Y':
532 /* save the number of uninstall keys so we can know if
533 * it changed */
534 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
535 &orig_num_keys, NULL, NULL, NULL,
536 NULL, NULL, NULL, NULL);
538 /* Delete the uninstall key. It has no subkeys, so
539 * this is easy. Do this before uninstalling, that
540 * may try to delete the key as well. */
541 RegDeleteKey(key_handle, subkey_name_buff);
543 /* Find existing .bat files before deleting them. */
544 find_bat_exe(TRUE);
546 /* Execute the uninstall program. Put it in double
547 * quotes if there is an embedded space. */
548 if (strchr(temp_string_buffer, ' ') != NULL)
550 char buf[BUFSIZE];
552 strcpy(buf, temp_string_buffer);
553 sprintf(temp_string_buffer, "\"%s\"", buf);
555 run_command(temp_string_buffer);
557 /* Check if an unistall reg key was deleted.
558 * if it was, we want to decrement key_index.
559 * if we don't do this, we will skip the key
560 * immediately after any key that we delete. */
561 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
562 &new_num_keys, NULL, NULL, NULL,
563 NULL, NULL, NULL, NULL);
564 if (new_num_keys < orig_num_keys)
565 key_index--;
567 input = 'y';
568 break;
570 case 'n':
571 case 'N':
572 /* Do not uninstall */
573 input = 'n';
574 break;
576 default: /* just drop through and redo the loop */
577 break;
580 } while (input != 'n' && input != 'y');
582 RegCloseKey(uninstall_key_handle);
585 RegCloseKey(key_handle);
587 return foundone;
589 #endif
592 * Find out information about the system.
594 static void
595 inspect_system(void)
597 char *p;
598 char buf[BUFSIZE];
599 FILE *fd;
600 int i;
601 int foundone;
603 /* This may take a little while, let the user know what we're doing. */
604 printf("Inspecting system...\n");
607 * If $VIM is set, check that it's pointing to our directory.
609 p = getenv("VIM");
610 if (p != NULL && pathcmp(p, -1, installdir, runtimeidx - 1) != 0)
612 printf("------------------------------------------------------\n");
613 printf("$VIM is set to \"%s\".\n", p);
614 printf("This is different from where this version of Vim is:\n");
615 strcpy(buf, installdir);
616 *(buf + runtimeidx - 1) = NUL;
617 printf("\"%s\"\n", buf);
618 printf("You must adjust or remove the setting of $VIM,\n");
619 if (interactive)
621 printf("to be able to use this install program.\n");
622 myexit(1);
624 printf("otherwise Vim WILL NOT WORK properly!\n");
625 printf("------------------------------------------------------\n");
629 * If $VIMRUNTIME is set, check that it's pointing to our runtime directory.
631 p = getenv("VIMRUNTIME");
632 if (p != NULL && pathcmp(p, -1, installdir, -1) != 0)
634 printf("------------------------------------------------------\n");
635 printf("$VIMRUNTIME is set to \"%s\".\n", p);
636 printf("This is different from where this version of Vim is:\n");
637 printf("\"%s\"\n", installdir);
638 printf("You must adjust or remove the setting of $VIMRUNTIME,\n");
639 if (interactive)
641 printf("to be able to use this install program.\n");
642 myexit(1);
644 printf("otherwise Vim WILL NOT WORK properly!\n");
645 printf("------------------------------------------------------\n");
649 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
651 find_bat_exe(FALSE);
654 * A .exe in the install directory may be found anyway on Windows 2000.
655 * Check for this situation and find another executable if necessary.
656 * w.briscoe@ponl.com 2001-01-20
658 foundone = 0;
659 for (i = 1; i < TARGET_COUNT; ++i)
661 findoldfile(&(targets[i].oldexe));
662 if (targets[i].oldexe != NULL)
663 foundone = 1;
666 if (foundone)
668 printf("Warning: Found Vim executable(s) in your $PATH:\n");
669 for (i = 1; i < TARGET_COUNT; ++i)
670 if (targets[i].oldexe != NULL)
671 printf("%s\n", targets[i].oldexe);
672 printf("It will be used instead of the version you are installing.\n");
673 printf("Please delete or rename it, or adjust your $PATH setting.\n");
677 * Check if there is an existing ../_vimrc or ../.vimrc file.
679 strcpy(oldvimrc, installdir);
680 strcpy(oldvimrc + runtimeidx, "_vimrc");
681 if ((fd = fopen(oldvimrc, "r")) == NULL)
683 strcpy(oldvimrc + runtimeidx, "vimrc~1"); /* short version of .vimrc */
684 if ((fd = fopen(oldvimrc, "r")) == NULL)
686 strcpy(oldvimrc + runtimeidx, ".vimrc");
687 fd = fopen(oldvimrc, "r");
690 if (fd != NULL)
691 fclose(fd);
692 else
693 *oldvimrc = NUL;
695 #if 0 /* currently not used */
697 * Get default home directory.
698 * Prefer $HOME if it's set. For Win NT use $HOMEDRIVE and $HOMEPATH.
699 * Otherwise, if there is a "c:" drive use that.
701 p = getenv("HOME");
702 if (p != NULL && *p != NUL && strlen(p) < BUFSIZE)
703 strcpy(homedir, p);
704 else
706 p = getenv("HOMEDRIVE");
707 if (p != NULL && *p != NUL && strlen(p) + 2 < BUFSIZE)
709 strcpy(homedir, p);
710 p = getenv("HOMEPATH");
711 if (p != NULL && *p != NUL && strlen(homedir) + strlen(p) < BUFSIZE)
712 strcat(homedir, p);
713 else
714 strcat(homedir, "\\");
716 else
718 struct stat st;
720 if (stat("c:\\", &st) == 0)
721 strcpy(homedir, "c:\\");
722 else
723 *homedir = NUL;
726 #endif
730 * Add a dummy choice to avoid that the numbering changes depending on items
731 * in the environment. The user may type a number he remembered without
732 * looking.
734 static void
735 add_dummy_choice(void)
737 choices[choice_count].installfunc = NULL;
738 choices[choice_count].active = 0;
739 choices[choice_count].changefunc = NULL;
740 choices[choice_count].installfunc = NULL;
741 ++choice_count;
744 /***********************************************
745 * stuff for creating the batch files.
749 * Install the vim.bat, gvim.bat, etc. files.
751 static void
752 install_bat_choice(int idx)
754 char *batpath = targets[choices[idx].arg].batpath;
755 char *oldname = targets[choices[idx].arg].oldbat;
756 char *exename = targets[choices[idx].arg].exenamearg;
757 char *vimarg = targets[choices[idx].arg].exearg;
758 FILE *fd;
760 if (*batpath != NUL)
762 fd = fopen(batpath, "w");
763 if (fd == NULL)
764 printf("\nERROR: Cannot open \"%s\" for writing.\n", batpath);
765 else
767 need_uninstall_entry = 1;
769 fprintf(fd, "@echo off\n");
770 fprintf(fd, "rem -- Run Vim --\n");
771 fprintf(fd, "\n");
773 /* Don't use double quotes for the "set" argument, also when it
774 * contains a space. The quotes would be included in the value
775 * for MSDOS and NT.
776 * The order of preference is:
777 * 1. $VIMRUNTIME/vim.exe (user preference)
778 * 2. $VIM/vim70/vim.exe (hard coded version)
779 * 3. installdir/vim.exe (hard coded install directory)
781 fprintf(fd, "set VIM_EXE_DIR=%s\n", installdir);
782 fprintf(fd, "if exist \"%%VIM%%\\%s\\%s\" set VIM_EXE_DIR=%%VIM%%\\%s\n",
783 VIM_VERSION_NODOT, exename, VIM_VERSION_NODOT);
784 fprintf(fd, "if exist \"%%VIMRUNTIME%%\\%s\" set VIM_EXE_DIR=%%VIMRUNTIME%%\n", exename);
785 fprintf(fd, "\n");
787 /* Give an error message when the executable could not be found. */
788 fprintf(fd, "if exist \"%%VIM_EXE_DIR%%\\%s\" goto havevim\n",
789 exename);
790 fprintf(fd, "echo \"%%VIM_EXE_DIR%%\\%s\" not found\n", exename);
791 fprintf(fd, "goto eof\n");
792 fprintf(fd, "\n");
793 fprintf(fd, ":havevim\n");
795 fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
796 fprintf(fd, "set VIMARGS=\n");
797 if (*exename == 'g')
798 fprintf(fd, "set VIMNOFORK=\n");
799 fprintf(fd, ":loopstart\n");
800 fprintf(fd, "if .%%1==. goto loopend\n");
801 if (*exename == 'g')
803 fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
804 fprintf(fd, "set VIMNOFORK=1\n");
805 fprintf(fd, ":noforkarg\n");
807 fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
808 fprintf(fd, "shift\n");
809 fprintf(fd, "goto loopstart\n");
810 fprintf(fd, ":loopend\n");
811 fprintf(fd, "\n");
813 fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n");
814 fprintf(fd, "\n");
816 /* For gvim.exe use "start" to avoid that the console window stays
817 * open. */
818 if (*exename == 'g')
820 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
821 fprintf(fd, "start ");
824 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
825 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
826 exename, vimarg);
827 fprintf(fd, "goto eof\n");
828 fprintf(fd, "\n");
830 if (*exename == 'g')
832 fprintf(fd, ":nofork\n");
833 fprintf(fd, "start /w ");
834 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
835 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
836 exename, vimarg);
837 fprintf(fd, "goto eof\n");
838 fprintf(fd, "\n");
841 fprintf(fd, ":ntaction\n");
842 fprintf(fd, "rem for WinNT we can use %%*\n");
844 /* For gvim.exe use "start /b" to avoid that the console window
845 * stays open. */
846 if (*exename == 'g')
848 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
849 fprintf(fd, "start \"dummy\" /b ");
852 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
853 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n", exename, vimarg);
854 fprintf(fd, "goto eof\n");
855 fprintf(fd, "\n");
857 if (*exename == 'g')
859 fprintf(fd, ":noforknt\n");
860 fprintf(fd, "start \"dummy\" /b /wait ");
861 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
862 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n",
863 exename, vimarg);
866 fprintf(fd, "\n:eof\n");
867 fprintf(fd, "set VIMARGS=\n");
868 if (*exename == 'g')
869 fprintf(fd, "set VIMNOFORK=\n");
871 fclose(fd);
872 printf("%s has been %s\n", batpath,
873 oldname == NULL ? "created" : "overwritten");
879 * Make the text string for choice "idx".
880 * The format "fmt" is must have one %s item, which "arg" is used for.
882 static void
883 alloc_text(int idx, char *fmt, char *arg)
885 if (choices[idx].text != NULL)
886 free(choices[idx].text);
888 choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
889 sprintf(choices[idx].text, fmt, arg);
893 * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
895 static void
896 toggle_bat_choice(int idx)
898 char *batname = targets[choices[idx].arg].batpath;
899 char *oldname = targets[choices[idx].arg].oldbat;
901 if (*batname == NUL)
903 alloc_text(idx, " Overwrite %s", oldname);
904 strcpy(batname, oldname);
906 else
908 alloc_text(idx, " Do NOT overwrite %s", oldname);
909 *batname = NUL;
914 * Do some work for a batch file entry: Append the batch file name to the path
915 * and set the text for the choice.
917 static void
918 set_bat_text(int idx, char *batpath, char *name)
920 strcat(batpath, name);
922 alloc_text(idx, " Create %s", batpath);
926 * Select a directory to write the batch file line.
928 static void
929 change_bat_choice(int idx)
931 char *path;
932 char *batpath;
933 char *name;
934 int n;
935 char *s;
936 char *p;
937 int count;
938 char **names = NULL;
939 int i;
940 int target = choices[idx].arg;
942 name = targets[target].batname;
943 batpath = targets[target].batpath;
945 path = getenv("PATH");
946 if (path == NULL)
948 printf("\nERROR: The variable $PATH is not set\n");
949 return;
953 * first round: count number of names in path;
954 * second round: save names to names[].
956 for (;;)
958 count = 1;
959 for (p = path; *p; )
961 s = strchr(p, ';');
962 if (s == NULL)
963 s = p + strlen(p);
964 if (names != NULL)
966 names[count] = alloc((int)(s - p) + 1);
967 strncpy(names[count], p, s - p);
968 names[count][s - p] = NUL;
970 ++count;
971 p = s;
972 if (*p != NUL)
973 ++p;
975 if (names != NULL)
976 break;
977 names = alloc((int)(count + 1) * sizeof(char *));
979 names[0] = alloc(50);
980 sprintf(names[0], "Select directory to create %s in:", name);
981 names[count] = alloc(50);
982 if (choices[idx].arg == 0)
983 sprintf(names[count], "Do not create any .bat file.");
984 else
985 sprintf(names[count], "Do not create a %s file.", name);
986 n = get_choice(names, count + 1);
988 if (n == count)
990 /* Selected last item, don't create bat file. */
991 *batpath = NUL;
992 if (choices[idx].arg != 0)
993 alloc_text(idx, " Do NOT create %s", name);
995 else
997 /* Selected one of the paths. For the first item only keep the path,
998 * for the others append the batch file name. */
999 strcpy(batpath, names[n]);
1000 add_pathsep(batpath);
1001 if (choices[idx].arg != 0)
1002 set_bat_text(idx, batpath, name);
1005 for (i = 0; i <= count; ++i)
1006 free(names[i]);
1007 free(names);
1010 char *bat_text_yes = "Install .bat files to use Vim at the command line:";
1011 char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
1013 static void
1014 change_main_bat_choice(int idx)
1016 int i;
1018 /* let the user select a default directory or NONE */
1019 change_bat_choice(idx);
1021 if (targets[0].batpath[0] != NUL)
1022 choices[idx].text = bat_text_yes;
1023 else
1024 choices[idx].text = bat_text_no;
1026 /* update the individual batch file selections */
1027 for (i = 1; i < TARGET_COUNT; ++i)
1029 /* Only make it active when the first item has a path and the vim.exe
1030 * or gvim.exe exists (there is a changefunc then). */
1031 if (targets[0].batpath[0] != NUL
1032 && choices[idx + i].changefunc != NULL)
1034 choices[idx + i].active = 1;
1035 if (choices[idx + i].changefunc == change_bat_choice
1036 && targets[i].batpath[0] != NUL)
1038 strcpy(targets[i].batpath, targets[0].batpath);
1039 set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
1042 else
1043 choices[idx + i].active = 0;
1048 * Initialize a choice for creating a batch file.
1050 static void
1051 init_bat_choice(int target)
1053 char *batpath = targets[target].batpath;
1054 char *oldbat = targets[target].oldbat;
1055 char *p;
1056 int i;
1058 choices[choice_count].arg = target;
1059 choices[choice_count].installfunc = install_bat_choice;
1060 choices[choice_count].active = 1;
1061 choices[choice_count].text = NULL; /* will be set below */
1062 if (oldbat != NULL)
1064 /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
1065 choices[choice_count].changefunc = toggle_bat_choice;
1066 *batpath = NUL;
1067 toggle_bat_choice(choice_count);
1069 else
1071 if (default_bat_dir != NULL)
1072 /* Prefer using the same path as an existing .bat file. */
1073 strcpy(batpath, default_bat_dir);
1074 else
1076 /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
1077 * $WINDIR by default, if it's empty the first item in $PATH. */
1078 p = getenv("WINDIR");
1079 if (p != NULL && *p != NUL)
1080 strcpy(batpath, p);
1081 else
1083 p = getenv("PATH");
1084 if (p == NULL || *p == NUL) /* "cannot happen" */
1085 strcpy(batpath, "C:/Windows");
1086 else
1088 i = 0;
1089 while (*p != NUL && *p != ';')
1090 batpath[i++] = *p++;
1091 batpath[i] = NUL;
1095 add_pathsep(batpath);
1096 set_bat_text(choice_count, batpath, targets[target].batname);
1098 choices[choice_count].changefunc = change_bat_choice;
1100 ++choice_count;
1104 * Set up the choices for installing .bat files.
1105 * For these items "arg" is the index in targets[].
1107 static void
1108 init_bat_choices(void)
1110 int i;
1112 /* The first item is used to switch installing batch files on/off and
1113 * setting the default path. */
1114 choices[choice_count].text = bat_text_yes;
1115 choices[choice_count].changefunc = change_main_bat_choice;
1116 choices[choice_count].installfunc = NULL;
1117 choices[choice_count].active = 1;
1118 choices[choice_count].arg = 0;
1119 ++choice_count;
1121 /* Add items for each batch file target. Only used when not disabled by
1122 * the first item. When a .exe exists, don't offer to create a .bat. */
1123 for (i = 1; i < TARGET_COUNT; ++i)
1124 if (targets[i].oldexe == NULL
1125 && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
1126 init_bat_choice(i);
1127 else
1128 add_dummy_choice();
1132 * Install the vimrc file.
1134 /*ARGSUSED*/
1135 static void
1136 install_vimrc(int idx)
1138 FILE *fd, *tfd;
1139 char *fname;
1141 /* If an old vimrc file exists, overwrite it.
1142 * Otherwise create a new one. */
1143 if (*oldvimrc != NUL)
1144 fname = oldvimrc;
1145 else
1146 fname = vimrc;
1148 fd = fopen(fname, "w");
1149 if (fd == NULL)
1151 printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
1152 return;
1154 switch (compat_choice)
1156 case compat_vi:
1157 fprintf(fd, "set compatible\n");
1158 break;
1159 case compat_some_enhancements:
1160 fprintf(fd, "set nocompatible\n");
1161 break;
1162 case compat_all_enhancements:
1163 fprintf(fd, "set nocompatible\n");
1164 fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
1165 break;
1167 switch (remap_choice)
1169 case remap_no:
1170 break;
1171 case remap_win:
1172 fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
1173 break;
1175 switch (mouse_choice)
1177 case mouse_xterm:
1178 fprintf(fd, "behave xterm\n");
1179 break;
1180 case mouse_mswin:
1181 fprintf(fd, "behave mswin\n");
1182 break;
1184 if ((tfd = fopen("diff.exe", "r")) != NULL)
1186 /* Use the diff.exe that comes with the self-extracting gvim.exe. */
1187 fclose(tfd);
1188 fprintf(fd, "\n");
1189 fprintf(fd, "set diffexpr=MyDiff()\n");
1190 fprintf(fd, "function MyDiff()\n");
1191 fprintf(fd, " let opt = '-a --binary '\n");
1192 fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
1193 fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
1194 /* Use quotes only when needed, they may cause trouble. */
1195 fprintf(fd, " let arg1 = v:fname_in\n");
1196 fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
1197 fprintf(fd, " let arg2 = v:fname_new\n");
1198 fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
1199 fprintf(fd, " let arg3 = v:fname_out\n");
1200 fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
1202 /* If the path has a space: When using cmd.exe (Win NT/2000/XP) put
1203 * quotes around the whole command and around the diff command.
1204 * Otherwise put a double quote just before the space and at the
1205 * end of the command. Putting quotes around the whole thing
1206 * doesn't work on Win 95/98/ME. This is mostly guessed! */
1207 fprintf(fd, " let eq = ''\n");
1208 fprintf(fd, " if $VIMRUNTIME =~ ' '\n");
1209 fprintf(fd, " if &sh =~ '\\<cmd'\n");
1210 fprintf(fd, " let cmd = '\"\"' . $VIMRUNTIME . '\\diff\"'\n");
1211 fprintf(fd, " let eq = '\"'\n");
1212 fprintf(fd, " else\n");
1213 fprintf(fd, " let cmd = substitute($VIMRUNTIME, ' ', '\" ', '') . '\\diff\"'\n");
1214 fprintf(fd, " endif\n");
1215 fprintf(fd, " else\n");
1216 fprintf(fd, " let cmd = $VIMRUNTIME . '\\diff'\n");
1217 fprintf(fd, " endif\n");
1218 fprintf(fd, " silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq\n");
1220 fprintf(fd, "endfunction\n");
1221 fprintf(fd, "\n");
1223 fclose(fd);
1224 printf("%s has been written\n", fname);
1227 static void
1228 change_vimrc_choice(int idx)
1230 if (choices[idx].installfunc != NULL)
1232 /* Switch to NOT change or create a vimrc file. */
1233 if (*oldvimrc != NUL)
1234 alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
1235 else
1236 alloc_text(idx, "Do NOT create startup file %s", vimrc);
1237 choices[idx].installfunc = NULL;
1238 choices[idx + 1].active = 0;
1239 choices[idx + 2].active = 0;
1240 choices[idx + 3].active = 0;
1242 else
1244 /* Switch to change or create a vimrc file. */
1245 if (*oldvimrc != NUL)
1246 alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
1247 else
1248 alloc_text(idx, "Create startup file %s with:", vimrc);
1249 choices[idx].installfunc = install_vimrc;
1250 choices[idx + 1].active = 1;
1251 choices[idx + 2].active = 1;
1252 choices[idx + 3].active = 1;
1257 * Change the choice how to run Vim.
1259 static void
1260 change_run_choice(int idx)
1262 compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
1263 alloc_text(idx, compat_text, compat_choices[compat_choice]);
1267 * Change the choice if keys are to be remapped.
1269 static void
1270 change_remap_choice(int idx)
1272 remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
1273 alloc_text(idx, remap_text, remap_choices[remap_choice]);
1277 * Change the choice how to select text.
1279 static void
1280 change_mouse_choice(int idx)
1282 mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
1283 alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
1286 static void
1287 init_vimrc_choices(void)
1289 /* set path for a new _vimrc file (also when not used) */
1290 strcpy(vimrc, installdir);
1291 strcpy(vimrc + runtimeidx, "_vimrc");
1293 /* Set opposite value and then toggle it by calling change_vimrc_choice() */
1294 if (*oldvimrc == NUL)
1295 choices[choice_count].installfunc = NULL;
1296 else
1297 choices[choice_count].installfunc = install_vimrc;
1298 choices[choice_count].text = NULL;
1299 change_vimrc_choice(choice_count);
1300 choices[choice_count].changefunc = change_vimrc_choice;
1301 choices[choice_count].active = 1;
1302 ++choice_count;
1304 /* default way to run Vim */
1305 alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
1306 choices[choice_count].changefunc = change_run_choice;
1307 choices[choice_count].installfunc = NULL;
1308 choices[choice_count].active = (*oldvimrc == NUL);
1309 ++choice_count;
1311 /* Whether to remap keys */
1312 alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
1313 choices[choice_count].changefunc = change_remap_choice;
1314 choices[choice_count].installfunc = NULL;;
1315 choices[choice_count].active = (*oldvimrc == NUL);
1316 ++choice_count;
1318 /* default way to use the mouse */
1319 alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
1320 choices[choice_count].changefunc = change_mouse_choice;
1321 choices[choice_count].installfunc = NULL;;
1322 choices[choice_count].active = (*oldvimrc == NUL);
1323 ++choice_count;
1327 * Add some entries to the registry:
1328 * - to add "Edit with Vim" to the context * menu
1329 * - to add Vim to the "Open with..." list
1330 * - to uninstall Vim
1332 /*ARGSUSED*/
1333 static void
1334 install_registry(void)
1336 #if defined(DJGPP) || defined(WIN3264) || defined(UNIX_LINT)
1337 FILE *fd;
1338 const char *vim_ext_ThreadingModel = "Apartment";
1339 const char *vim_ext_name = "Vim Shell Extension";
1340 const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
1341 char buf[BUFSIZE];
1343 fd = fopen("vim.reg", "w");
1344 if (fd == NULL)
1345 printf("ERROR: Could not open vim.reg for writing\n");
1346 else
1348 double_bs(installdir, buf); /* double the backslashes */
1351 * Write the registry entries for the "Edit with Vim" menu.
1353 fprintf(fd, "REGEDIT4\n");
1354 fprintf(fd, "\n");
1355 if (install_popup)
1357 char bufg[BUFSIZE];
1358 struct stat st;
1360 if (stat("gvimext.dll", &st) >= 0)
1361 strcpy(bufg, buf);
1362 else
1363 /* gvimext.dll is in gvimext subdir */
1364 sprintf(bufg, "%sgvimext\\\\", buf);
1366 printf("Creating \"Edit with Vim\" popup menu entry\n");
1368 fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\%s]\n", vim_ext_clsid);
1369 fprintf(fd, "@=\"%s\"\n", vim_ext_name);
1370 fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\%s\\InProcServer32]\n",
1371 vim_ext_clsid);
1372 fprintf(fd, "@=\"%sgvimext.dll\"\n", bufg);
1373 fprintf(fd, "\"ThreadingModel\"=\"%s\"\n", vim_ext_ThreadingModel);
1374 fprintf(fd, "\n");
1375 fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\shellex\\ContextMenuHandlers\\gvim]\n");
1376 fprintf(fd, "@=\"%s\"\n", vim_ext_clsid);
1377 fprintf(fd, "\n");
1378 fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved]\n");
1379 fprintf(fd, "\"%s\"=\"%s\"\n", vim_ext_clsid, vim_ext_name);
1380 fprintf(fd, "\n");
1381 fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Vim\\Gvim]\n");
1382 fprintf(fd, "\"path\"=\"%sgvim.exe\"\n", buf);
1383 fprintf(fd, "\n");
1386 if (install_openwith)
1388 printf("Creating \"Open with ...\" list entry\n");
1390 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe]\n\n");
1391 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell]\n\n");
1392 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell\\edit]\n\n");
1393 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell\\edit\\command]\n");
1394 fprintf(fd, "@=\"%sgvim.exe \\\"%%1\\\"\"\n\n", buf);
1395 fprintf(fd, "[HKEY_CLASSES_ROOT\\.htm\\OpenWithList\\gvim.exe]\n\n");
1396 fprintf(fd, "[HKEY_CLASSES_ROOT\\.vim\\OpenWithList\\gvim.exe]\n\n");
1397 fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\OpenWithList\\gvim.exe]\n\n");
1400 printf("Creating an uninstall entry\n");
1402 /* The registry entries for uninstalling the menu */
1403 fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT "]\n");
1405 /* For the NSIS installer use the generated uninstaller. */
1406 if (interactive)
1408 fprintf(fd, "\"DisplayName\"=\"Vim " VIM_VERSION_SHORT "\"\n");
1409 fprintf(fd, "\"UninstallString\"=\"%suninstal.exe\"\n", buf);
1411 else
1413 fprintf(fd, "\"DisplayName\"=\"Vim " VIM_VERSION_SHORT " (self-installing)\"\n");
1414 fprintf(fd, "\"UninstallString\"=\"%suninstall-gui.exe\"\n", buf);
1417 fclose(fd);
1419 run_command("regedit /s vim.reg");
1421 remove("vim.reg");
1423 #endif /* if defined(DJGPP) || defined(WIN3264) */
1426 static void
1427 change_popup_choice(int idx)
1429 if (install_popup == 0)
1431 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";
1432 install_popup = 1;
1434 else
1436 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";
1437 install_popup = 0;
1442 * Only add the choice for the popup menu entry when gvim.exe was found and
1443 * both gvimext.dll and regedit.exe exist.
1445 static void
1446 init_popup_choice(void)
1448 struct stat st;
1450 if (has_gvim
1451 && (stat("gvimext.dll", &st) >= 0
1452 || stat("gvimext/gvimext.dll", &st) >= 0)
1453 #ifndef WIN3264
1454 && searchpath("regedit.exe") != NULL
1455 #endif
1458 choices[choice_count].changefunc = change_popup_choice;
1459 choices[choice_count].installfunc = NULL;
1460 choices[choice_count].active = 1;
1461 change_popup_choice(choice_count); /* set the text */
1462 ++choice_count;
1464 else
1465 add_dummy_choice();
1468 static void
1469 change_openwith_choice(int idx)
1471 if (install_openwith == 0)
1473 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";
1474 install_openwith = 1;
1476 else
1478 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";
1479 install_openwith = 0;
1484 * Only add the choice for the open-with menu entry when gvim.exe was found
1485 * and and regedit.exe exist.
1487 static void
1488 init_openwith_choice(void)
1490 if (has_gvim
1491 #ifndef WIN3264
1492 && searchpath("regedit.exe") != NULL
1493 #endif
1496 choices[choice_count].changefunc = change_openwith_choice;
1497 choices[choice_count].installfunc = NULL;
1498 choices[choice_count].active = 1;
1499 change_openwith_choice(choice_count); /* set the text */
1500 ++choice_count;
1502 else
1503 add_dummy_choice();
1506 #ifdef WIN3264
1507 /* create_shortcut
1509 * Create a shell link.
1511 * returns 0 on failure, non-zero on successful completion.
1513 * NOTE: Currently untested with mingw.
1516 create_shortcut(
1517 const char *shortcut_name,
1518 const char *iconfile_path,
1519 int iconindex,
1520 const char *shortcut_target,
1521 const char *shortcut_args,
1522 const char *workingdir
1525 IShellLink *shelllink_ptr;
1526 HRESULT hres;
1527 IPersistFile *persistfile_ptr;
1529 /* Initialize COM library */
1530 hres = CoInitialize(NULL);
1531 if (!SUCCEEDED(hres))
1533 printf("Error: Could not open the COM library. Not creating shortcut.\n");
1534 return FAIL;
1537 /* Instantiate a COM object for the ShellLink, store a pointer to it
1538 * in shelllink_ptr. */
1539 hres = CoCreateInstance(&CLSID_ShellLink,
1540 NULL,
1541 CLSCTX_INPROC_SERVER,
1542 &IID_IShellLink,
1543 (void **) &shelllink_ptr);
1545 if (SUCCEEDED(hres)) /* If the instantiation was successful... */
1547 /* ...Then build a PersistFile interface for the ShellLink so we can
1548 * save it as a file after we build it. */
1549 hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
1550 &IID_IPersistFile, (void **) &persistfile_ptr);
1552 if (SUCCEEDED(hres))
1554 wchar_t wsz[BUFSIZE];
1556 /* translate the (possibly) multibyte shortcut filename to windows
1557 * Unicode so it can be used as a file name.
1559 MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
1561 /* set the attributes */
1562 shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
1563 shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
1564 workingdir);
1565 shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
1566 iconfile_path, iconindex);
1567 shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
1569 /* save the shortcut to a file and return the PersistFile object*/
1570 persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
1571 persistfile_ptr->lpVtbl->Release(persistfile_ptr);
1573 else
1575 printf("QueryInterface Error\n");
1576 return FAIL;
1579 /* Return the ShellLink object */
1580 shelllink_ptr->lpVtbl->Release(shelllink_ptr);
1582 else
1584 printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
1585 return FAIL;
1588 return OK;
1592 * Build a path to where we will put a specified link.
1594 * Return 0 on error, non-zero on success
1597 build_link_name(
1598 char *link_path,
1599 const char *link_name,
1600 const char *shell_folder_name)
1602 char shell_folder_path[BUFSIZE];
1604 if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
1606 printf("An error occurred while attempting to find the path to %s.\n",
1607 shell_folder_name);
1608 return FAIL;
1611 /* Make sure the directory exists (create Start Menu\Programs\Vim).
1612 * Ignore errors if it already exists. */
1613 vim_mkdir(shell_folder_path, 0755);
1615 /* build the path to the shortcut and the path to gvim.exe */
1616 sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
1618 return OK;
1621 static int
1622 build_shortcut(
1623 const char *name, /* Name of the shortcut */
1624 const char *exename, /* Name of the executable (e.g., vim.exe) */
1625 const char *args,
1626 const char *shell_folder,
1627 const char *workingdir)
1629 char executable_path[BUFSIZE];
1630 char link_name[BUFSIZE];
1632 sprintf(executable_path, "%s\\%s", installdir, exename);
1634 if (build_link_name(link_name, name, shell_folder) == FAIL)
1636 printf("An error has occurred. A shortcut to %s will not be created %s.\n",
1637 name,
1638 *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
1639 return FAIL;
1642 /* Create the shortcut: */
1643 return create_shortcut(link_name, executable_path, 0,
1644 executable_path, args, workingdir);
1648 * We used to use "homedir" as the working directory, but that is a bad choice
1649 * on multi-user systems. Not specifying a directory appears to work best.
1651 #define WORKDIR ""
1654 * Create shortcut(s) in the Start Menu\Programs\Vim folder.
1656 static void
1657 install_start_menu(int idx)
1659 need_uninstall_entry = 1;
1660 printf("Creating start menu\n");
1661 if (has_vim)
1663 if (build_shortcut("Vim", "vim.exe", "",
1664 VIM_STARTMENU, WORKDIR) == FAIL)
1665 return;
1666 if (build_shortcut("Vim Read-only", "vim.exe", "-R",
1667 VIM_STARTMENU, WORKDIR) == FAIL)
1668 return;
1669 if (build_shortcut("Vim Diff", "vim.exe", "-d",
1670 VIM_STARTMENU, WORKDIR) == FAIL)
1671 return;
1673 if (has_gvim)
1675 if (build_shortcut("gVim", "gvim.exe", "",
1676 VIM_STARTMENU, WORKDIR) == FAIL)
1677 return;
1678 if (build_shortcut("gVim Easy", "gvim.exe", "-y",
1679 VIM_STARTMENU, WORKDIR) == FAIL)
1680 return;
1681 if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
1682 VIM_STARTMENU, WORKDIR) == FAIL)
1683 return;
1684 if (build_shortcut("gVim Diff", "gvim.exe", "-d",
1685 VIM_STARTMENU, WORKDIR) == FAIL)
1686 return;
1688 if (build_shortcut("Uninstall",
1689 interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
1690 VIM_STARTMENU, installdir) == FAIL)
1691 return;
1692 /* For Windows NT the working dir of the vimtutor.bat must be right,
1693 * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
1694 if (build_shortcut("Vim tutor", "vimtutor.bat", "",
1695 VIM_STARTMENU, installdir) == FAIL)
1696 return;
1697 if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
1698 VIM_STARTMENU, WORKDIR) == FAIL)
1699 return;
1701 char shell_folder_path[BUFSIZE];
1703 /* Creating the URL shortcut works a bit differently... */
1704 if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
1706 printf("Finding the path of the Start menu failed\n");
1707 return ;
1709 add_pathsep(shell_folder_path);
1710 strcat(shell_folder_path, "Vim Online.url");
1711 if (!WritePrivateProfileString("InternetShortcut", "URL",
1712 "http://vim.sf.net/", shell_folder_path))
1714 printf("Creating the Vim online URL failed\n");
1715 return;
1720 static void
1721 toggle_startmenu_choice(int idx)
1723 if (choices[idx].installfunc == NULL)
1725 choices[idx].installfunc = install_start_menu;
1726 choices[idx].text = "Add Vim to the Start menu";
1728 else
1730 choices[idx].installfunc = NULL;
1731 choices[idx].text = "Do NOT add Vim to the Start menu";
1736 * Function to actually create the shortcuts
1738 * Currently I am supplying no working directory to the shortcut. This
1739 * means that the initial working dir will be:
1740 * - the location of the shortcut if no file is supplied
1741 * - the location of the file being edited if a file is supplied (ie via
1742 * drag and drop onto the shortcut).
1744 void
1745 install_shortcut_gvim(int idx)
1747 /* Create shortcut(s) on the desktop */
1748 if (choices[idx].arg)
1750 (void)build_shortcut(icon_names[0], "gvim.exe",
1751 "", "desktop", WORKDIR);
1752 need_uninstall_entry = 1;
1756 void
1757 install_shortcut_evim(int idx)
1759 if (choices[idx].arg)
1761 (void)build_shortcut(icon_names[1], "gvim.exe",
1762 "-y", "desktop", WORKDIR);
1763 need_uninstall_entry = 1;
1767 void
1768 install_shortcut_gview(int idx)
1770 if (choices[idx].arg)
1772 (void)build_shortcut(icon_names[2], "gvim.exe",
1773 "-R", "desktop", WORKDIR);
1774 need_uninstall_entry = 1;
1778 void
1779 toggle_shortcut_choice(int idx)
1781 char *arg;
1783 if (choices[idx].installfunc == install_shortcut_gvim)
1784 arg = "gVim";
1785 else if (choices[idx].installfunc == install_shortcut_evim)
1786 arg = "gVim Easy";
1787 else
1788 arg = "gVim Read-only";
1789 if (choices[idx].arg)
1791 choices[idx].arg = 0;
1792 alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
1794 else
1796 choices[idx].arg = 1;
1797 alloc_text(idx, "Create a desktop icon for %s", arg);
1800 #endif /* WIN3264 */
1802 static void
1803 init_startmenu_choice(void)
1805 #ifdef WIN3264
1806 /* Start menu */
1807 choices[choice_count].changefunc = toggle_startmenu_choice;
1808 choices[choice_count].installfunc = NULL;
1809 choices[choice_count].active = 1;
1810 toggle_startmenu_choice(choice_count); /* set the text */
1811 ++choice_count;
1812 #else
1813 add_dummy_choice();
1814 #endif
1818 * Add the choice for the desktop shortcuts.
1820 static void
1821 init_shortcut_choices(void)
1823 #ifdef WIN3264
1824 /* Shortcut to gvim */
1825 choices[choice_count].text = NULL;
1826 choices[choice_count].arg = 0;
1827 choices[choice_count].active = has_gvim;
1828 choices[choice_count].changefunc = toggle_shortcut_choice;
1829 choices[choice_count].installfunc = install_shortcut_gvim;
1830 toggle_shortcut_choice(choice_count);
1831 ++choice_count;
1833 /* Shortcut to evim */
1834 choices[choice_count].text = NULL;
1835 choices[choice_count].arg = 0;
1836 choices[choice_count].active = has_gvim;
1837 choices[choice_count].changefunc = toggle_shortcut_choice;
1838 choices[choice_count].installfunc = install_shortcut_evim;
1839 toggle_shortcut_choice(choice_count);
1840 ++choice_count;
1842 /* Shortcut to gview */
1843 choices[choice_count].text = NULL;
1844 choices[choice_count].arg = 0;
1845 choices[choice_count].active = has_gvim;
1846 choices[choice_count].changefunc = toggle_shortcut_choice;
1847 choices[choice_count].installfunc = install_shortcut_gview;
1848 toggle_shortcut_choice(choice_count);
1849 ++choice_count;
1850 #else
1851 add_dummy_choice();
1852 add_dummy_choice();
1853 add_dummy_choice();
1854 #endif
1857 #ifdef WIN3264
1859 * Attempt to register OLE for Vim.
1861 static void
1862 install_OLE_register(void)
1864 char register_command_string[BUFSIZE + 30];
1866 printf("\n--- Attempting to register Vim with OLE ---\n");
1867 printf("(There is no message whether this works or not.)\n");
1869 #ifndef __CYGWIN__
1870 sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
1871 #else
1872 /* handle this differently for Cygwin which sometimes has trouble with
1873 * Windows-style pathnames here. */
1874 sprintf(register_command_string, "./gvim.exe -silent -register");
1875 #endif
1876 system(register_command_string);
1878 #endif /* WIN3264 */
1881 * Remove the last part of directory "path[]" to get its parent, and put the
1882 * result in "to[]".
1884 static void
1885 dir_remove_last(const char *path, char to[BUFSIZE])
1887 char c;
1888 long last_char_to_copy;
1889 long path_length = strlen(path);
1891 /* skip the last character just in case it is a '\\' */
1892 last_char_to_copy = path_length - 2;
1893 c = path[last_char_to_copy];
1895 while (c != '\\')
1897 last_char_to_copy--;
1898 c = path[last_char_to_copy];
1901 strncpy(to, path, (size_t)last_char_to_copy);
1902 to[last_char_to_copy] = NUL;
1905 static void
1906 set_directories_text(int idx)
1908 if (vimfiles_dir_choice == (int)vimfiles_dir_none)
1909 alloc_text(idx, "Do NOT create plugin directories%s", "");
1910 else
1911 alloc_text(idx, "Create plugin directories: %s",
1912 vimfiles_dir_choices[vimfiles_dir_choice]);
1916 * Change the directory that the vim plugin directories will be created in:
1917 * $HOME, $VIM or nowhere.
1919 static void
1920 change_directories_choice(int idx)
1922 int choice_count = TABLE_SIZE(vimfiles_dir_choices);
1924 /* Don't offer the $HOME choice if $HOME isn't set. */
1925 if (getenv("HOME") == NULL)
1926 --choice_count;
1927 vimfiles_dir_choice = get_choice(vimfiles_dir_choices, choice_count);
1928 set_directories_text(idx);
1932 * Create the plugin directories...
1934 /*ARGSUSED*/
1935 static void
1936 install_vimfilesdir(int idx)
1938 int i;
1939 char *p;
1940 char vimdir_path[BUFSIZE];
1941 char vimfiles_path[BUFSIZE];
1942 char tmp_dirname[BUFSIZE];
1944 /* switch on the location that the user wants the plugin directories
1945 * built in */
1946 switch (vimfiles_dir_choice)
1948 case vimfiles_dir_vim:
1950 /* Go to the %VIM% directory - check env first, then go one dir
1951 * below installdir if there is no %VIM% environment variable.
1952 * The accuracy of $VIM is checked in inspect_system(), so we
1953 * can be sure it is ok to use here. */
1954 p = getenv("VIM");
1955 if (p == NULL) /* No $VIM in path */
1956 dir_remove_last(installdir, vimdir_path);
1957 else
1958 strcpy(vimdir_path, p);
1959 break;
1961 case vimfiles_dir_home:
1963 /* Find the $HOME directory. Its existence was already checked. */
1964 p = getenv("HOME");
1965 if (p == NULL)
1967 printf("Internal error: $HOME is NULL\n");
1968 p = "c:\\";
1970 strcpy(vimdir_path, p);
1971 break;
1973 case vimfiles_dir_none:
1975 /* Do not create vim plugin directory */
1976 return;
1980 /* Now, just create the directory. If it already exists, it will fail
1981 * silently. */
1982 sprintf(vimfiles_path, "%s\\vimfiles", vimdir_path);
1983 vim_mkdir(vimfiles_path, 0755);
1985 printf("Creating the following directories in \"%s\":\n", vimfiles_path);
1986 for (i = 0; i < TABLE_SIZE(vimfiles_subdirs); i++)
1988 sprintf(tmp_dirname, "%s\\%s", vimfiles_path, vimfiles_subdirs[i]);
1989 printf(" %s", vimfiles_subdirs[i]);
1990 vim_mkdir(tmp_dirname, 0755);
1992 printf("\n");
1996 * Add the creation of runtime files to the setup sequence.
1998 static void
1999 init_directories_choice(void)
2001 struct stat st;
2002 char tmp_dirname[BUFSIZE];
2003 char *p;
2005 choices[choice_count].text = alloc(150);
2006 choices[choice_count].changefunc = change_directories_choice;
2007 choices[choice_count].installfunc = install_vimfilesdir;
2008 choices[choice_count].active = 1;
2010 /* Check if the "compiler" directory already exists. That's a good
2011 * indication that the plugin directories were already created. */
2012 if (getenv("HOME") != NULL)
2014 vimfiles_dir_choice = (int)vimfiles_dir_home;
2015 sprintf(tmp_dirname, "%s\\vimfiles\\compiler", getenv("HOME"));
2016 if (stat(tmp_dirname, &st) == 0)
2017 vimfiles_dir_choice = (int)vimfiles_dir_none;
2019 else
2021 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2022 p = getenv("VIM");
2023 if (p == NULL) /* No $VIM in path, use the install dir */
2024 dir_remove_last(installdir, tmp_dirname);
2025 else
2026 strcpy(tmp_dirname, p);
2027 strcat(tmp_dirname, "\\vimfiles\\compiler");
2028 if (stat(tmp_dirname, &st) == 0)
2029 vimfiles_dir_choice = (int)vimfiles_dir_none;
2032 set_directories_text(choice_count);
2033 ++choice_count;
2037 * Setup the choices and the default values.
2039 static void
2040 setup_choices(void)
2042 /* install the batch files */
2043 init_bat_choices();
2045 /* (over) write _vimrc file */
2046 init_vimrc_choices();
2048 /* Whether to add Vim to the popup menu */
2049 init_popup_choice();
2051 /* Whether to add Vim to the "Open With..." menu */
2052 init_openwith_choice();
2054 /* Whether to add Vim to the Start Menu. */
2055 init_startmenu_choice();
2057 /* Whether to add shortcuts to the Desktop. */
2058 init_shortcut_choices();
2060 /* Whether to create the runtime directories. */
2061 init_directories_choice();
2064 static void
2065 print_cmd_line_help(void)
2067 printf("Vim installer non-interactive command line arguments:\n");
2068 printf("\n");
2069 printf("-create-batfiles [vim gvim evim view gview vimdiff gvimdiff]\n");
2070 printf(" Create .bat files for Vim variants in the Windows directory.\n");
2071 printf("-create-vimrc\n");
2072 printf(" Create a default _vimrc file if one does not already exist.\n");
2073 printf("-install-popup\n");
2074 printf(" Install the Edit-with-Vim context menu entry\n");
2075 printf("-install-openwith\n");
2076 printf(" Add Vim to the \"Open With...\" context menu list\n");
2077 #ifdef WIN3264
2078 printf("-add-start-menu");
2079 printf(" Add Vim to the start menu\n");
2080 printf("-install-icons");
2081 printf(" Create icons for gVim executables on the desktop\n");
2082 #endif
2083 printf("-create-directories [vim|home]\n");
2084 printf(" Create runtime directories to drop plugins into; in the $VIM\n");
2085 printf(" or $HOME directory\n");
2086 #ifdef WIN3264
2087 printf("-register-OLE");
2088 printf(" Ignored\n");
2089 #endif
2090 printf("\n");
2094 * Setup installation choices based on command line switches
2096 static void
2097 command_line_setup_choices(int argc, char **argv)
2099 int i, j;
2101 for (i = 1; i < argc; i++)
2103 if (strcmp(argv[i], "-create-batfiles") == 0)
2105 if (i + 1 == argc)
2106 continue;
2107 while (argv[i + 1][0] != '-' && i < argc)
2109 i++;
2110 for (j = 1; j < TARGET_COUNT; ++j)
2111 if ((targets[j].exenamearg[0] == 'g' ? has_gvim : has_vim)
2112 && strcmp(argv[i], targets[j].name) == 0)
2114 init_bat_choice(j);
2115 break;
2117 if (j == TARGET_COUNT)
2118 printf("%s is not a valid choice for -create-batfiles\n",
2119 argv[i]);
2121 if (i + 1 == argc)
2122 break;
2125 else if (strcmp(argv[i], "-create-vimrc") == 0)
2127 /* Setup default vimrc choices. If there is already a _vimrc file,
2128 * it will NOT be overwritten.
2130 init_vimrc_choices();
2132 else if (strcmp(argv[i], "-install-popup") == 0)
2134 init_popup_choice();
2136 else if (strcmp(argv[i], "-install-openwith") == 0)
2138 init_openwith_choice();
2140 else if (strcmp(argv[i], "-add-start-menu") == 0)
2142 init_startmenu_choice();
2144 else if (strcmp(argv[i], "-install-icons") == 0)
2146 init_shortcut_choices();
2148 else if (strcmp(argv[i], "-create-directories") == 0)
2150 init_directories_choice();
2151 if (argv[i + 1][0] != '-')
2153 i++;
2154 if (strcmp(argv[i], "vim") == 0)
2155 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2156 else if (strcmp(argv[i], "home") == 0)
2158 if (getenv("HOME") == NULL) /* No $HOME in environment */
2159 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2160 else
2161 vimfiles_dir_choice = (int)vimfiles_dir_home;
2163 else
2165 printf("Unknown argument for -create-directories: %s\n",
2166 argv[i]);
2167 print_cmd_line_help();
2170 else /* No choice specified, default to vim directory */
2171 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2173 #ifdef WIN3264
2174 else if (strcmp(argv[i], "-register-OLE") == 0)
2176 /* This is always done when gvim is found */
2178 #endif
2179 else /* Unknown switch */
2181 printf("Got unknown argument argv[%d] = %s\n", i, argv[i]);
2182 print_cmd_line_help();
2189 * Show a few screens full of helpful information.
2191 static void
2192 show_help(void)
2194 static char *(items[]) =
2196 "Installing .bat files\n"
2197 "---------------------\n"
2198 "The vim.bat file is written in one of the directories in $PATH.\n"
2199 "This makes it possible to start Vim from the command line.\n"
2200 "If vim.exe can be found in $PATH, the choice for vim.bat will not be\n"
2201 "present. It is assumed you will use the existing vim.exe.\n"
2202 "If vim.bat can already be found in $PATH this is probably for an old\n"
2203 "version of Vim (but this is not checked!). You can overwrite it.\n"
2204 "If no vim.bat already exists, you can select one of the directories in\n"
2205 "$PATH for creating the batch file, or disable creating a vim.bat file.\n"
2206 "\n"
2207 "If you choose not to create the vim.bat file, Vim can still be executed\n"
2208 "in other ways, but not from the command line.\n"
2209 "\n"
2210 "The same applies to choices for gvim, evim, (g)view, and (g)vimdiff.\n"
2211 "The first item can be used to change the path for all of them.\n"
2213 "Creating a _vimrc file\n"
2214 "----------------------\n"
2215 "The _vimrc file is used to set options for how Vim behaves.\n"
2216 "The install program can create a _vimrc file with a few basic choices.\n"
2217 "You can edit this file later to tune your preferences.\n"
2218 "If you already have a _vimrc or .vimrc file it can be overwritten.\n"
2219 "Don't do that if you have made changes to it.\n"
2221 "Vim features\n"
2222 "------------\n"
2223 "(this choice is only available when creating a _vimrc file)\n"
2224 "1. Vim can run in Vi-compatible mode. Many nice Vim features are then\n"
2225 " disabled. In the not-Vi-compatible mode Vim is still mostly Vi\n"
2226 " compatible, but adds nice features like multi-level undo. Only\n"
2227 " choose Vi-compatible if you really need full Vi compatibility.\n"
2228 "2. Running Vim with some enhancements is useful when you want some of\n"
2229 " the nice Vim features, but have a slow computer and want to keep it\n"
2230 " really fast.\n"
2231 "3. Syntax highlighting shows many files in color. Not only does this look\n"
2232 " nice, it also makes it easier to spot errors and you can work faster.\n"
2233 " The other features include editing compressed files.\n"
2235 "Windows key mapping\n"
2236 "-------------------\n"
2237 "(this choice is only available when creating a _vimrc file)\n"
2238 "Under MS-Windows the CTRL-C key copies text to the clipboard and CTRL-V\n"
2239 "pastes text from the clipboard. There are a few more keys like these.\n"
2240 "Unfortunately, in Vim these keys normally have another meaning.\n"
2241 "1. Choose to have the keys like they normally are in Vim (useful if you\n"
2242 " also use Vim on other systems).\n"
2243 "2. Choose to have the keys work like they are used on MS-Windows (useful\n"
2244 " if you mostly work on MS-Windows).\n"
2246 "Mouse use\n"
2247 "---------\n"
2248 "(this choice is only available when creating a _vimrc file)\n"
2249 "The right mouse button can be used in two ways:\n"
2250 "1. The Unix way is to extend an existing selection. The popup menu is\n"
2251 " not available.\n"
2252 "2. The MS-Windows way is to show a popup menu, which allows you to\n"
2253 " copy/paste text, undo/redo, etc. Extending the selection can still be\n"
2254 " done by keeping SHIFT pressed while using the left mouse button\n"
2256 "Edit-with-Vim context menu entry\n"
2257 "--------------------------------\n"
2258 "(this choice is only available when gvim.exe and gvimext.dll are present)\n"
2259 "You can associate different file types with Vim, so that you can (double)\n"
2260 "click on a file to edit it with Vim. This means you have to individually\n"
2261 "select each file type.\n"
2262 "An alternative is the option offered here: Install an \"Edit with Vim\"\n"
2263 "entry in the popup menu for the right mouse button. This means you can\n"
2264 "edit any file with Vim.\n"
2266 "\"Open With...\" context menu entry\n"
2267 "--------------------------------\n"
2268 "(this choice is only available when gvim.exe is present)\n"
2269 "This option adds Vim to the \"Open With...\" entry in the popup menu for\n"
2270 "the right mouse button. This also makes it possible to edit HTML files\n"
2271 "directly from Internet Explorer.\n"
2273 "Add Vim to the Start menu\n"
2274 "-------------------------\n"
2275 "In Windows 95 and later, Vim can be added to the Start menu. This will\n"
2276 "create a submenu with an entry for vim, gvim, evim, vimdiff, etc..\n"
2278 "Icons on the desktop\n"
2279 "--------------------\n"
2280 "(these choices are only available when installing gvim)\n"
2281 "In Windows 95 and later, shortcuts (icons) can be created on the Desktop.\n"
2283 "Create plugin directories\n"
2284 "-------------------------\n"
2285 "Plugin directories allow extending Vim by dropping a file into a directory.\n"
2286 "This choice allows creating them in $HOME (if you have a home directory) or\n"
2287 "$VIM (used for everybody on the system).\n"
2289 NULL
2291 int i;
2292 int c;
2294 rewind(stdin);
2295 printf("\n");
2296 for (i = 0; items[i] != NULL; ++i)
2298 printf(items[i]);
2299 printf("\n");
2300 printf("Hit Enter to continue, b (back) or q (quit help): ");
2301 c = getchar();
2302 rewind(stdin);
2303 if (c == 'b' || c == 'B')
2305 if (i == 0)
2306 --i;
2307 else
2308 i -= 2;
2310 if (c == 'q' || c == 'Q')
2311 break;
2312 printf("\n");
2317 * Install the choices.
2319 static void
2320 install(void)
2322 int i;
2324 /* Install the selected choices. */
2325 for (i = 0; i < choice_count; ++i)
2326 if (choices[i].installfunc != NULL && choices[i].active)
2327 (choices[i].installfunc)(i);
2329 /* Add some entries to the registry, if needed. */
2330 if (install_popup
2331 || install_openwith
2332 || (need_uninstall_entry && interactive)
2333 || !interactive)
2334 install_registry();
2336 #ifdef WIN3264
2337 /* Register gvim with OLE. */
2338 if (has_gvim)
2339 install_OLE_register();
2340 #endif
2344 * request_choice
2346 static void
2347 request_choice(void)
2349 int i;
2351 printf("\n\nInstall will do for you:\n");
2352 for (i = 0; i < choice_count; ++i)
2353 if (choices[i].active)
2354 printf("%2d %s\n", i + 1, choices[i].text);
2355 printf("To change an item, enter its number\n\n");
2356 printf("Enter item number, h (help), d (do it) or q (quit): ");
2360 main(int argc, char **argv)
2362 int i;
2363 char buf[BUFSIZE];
2366 * Run interactively if there are no command line arguments.
2368 if (argc > 1)
2369 interactive = 0;
2370 else
2371 interactive = 1;
2373 /* Initialize this program. */
2374 do_inits(argv);
2376 #ifdef WIN3264
2377 if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
2379 /* Only check for already installed Vims. Used by NSIS installer. */
2380 i = uninstall_check();
2382 /* Find the value of $VIM, because NSIS isn't able to do this by
2383 * itself. */
2384 get_vim_env();
2386 /* When nothing found exit quietly. If something found wait for
2387 * return pressed. */
2388 if (i)
2389 myexit(0);
2390 exit(0);
2392 #endif
2394 printf("This program sets up the installation of Vim "
2395 VIM_VERSION_MEDIUM "\n\n");
2397 /* Check if the user unpacked the archives properly. */
2398 check_unpack();
2400 #ifdef WIN3264
2401 /* Check for already installed Vims. */
2402 if (interactive)
2403 uninstall_check();
2404 #endif
2406 /* Find out information about the system. */
2407 inspect_system();
2409 if (interactive)
2411 /* Setup all the choices. */
2412 setup_choices();
2414 /* Let the user change choices and finally install (or quit). */
2415 for (;;)
2417 request_choice();
2418 rewind(stdin);
2419 if (scanf("%99s", buf) == 1)
2421 if (isdigit(buf[0]))
2423 /* Change a choice. */
2424 i = atoi(buf);
2425 if (i > 0 && i <= choice_count && choices[i - 1].active)
2426 (choices[i - 1].changefunc)(i - 1);
2427 else
2428 printf("\nIllegal choice\n");
2430 else if (buf[0] == 'h' || buf[0] == 'H')
2432 /* Help */
2433 show_help();
2435 else if (buf[0] == 'd' || buf[0] == 'D')
2437 /* Install! */
2438 install();
2439 printf("\nThat finishes the installation. Happy Vimming!\n");
2440 break;
2442 else if (buf[0] == 'q' || buf[0] == 'Q')
2444 /* Quit */
2445 printf("\nExiting without anything done\n");
2446 break;
2448 else
2449 printf("\nIllegal choice\n");
2452 printf("\n");
2454 else
2457 * Run non-interactive - setup according to the command line switches
2459 command_line_setup_choices(argc, argv);
2460 install();
2463 myexit(0);
2464 /*NOTREACHED*/
2465 return 0;