comparison src/dosinst.c @ 7:3fc0f57ecb91 v7.0001

updated for version 7.0001
author vimboss
date Sun, 13 Jun 2004 20:20:40 +0000
parents
children f713fc55bf7b
comparison
equal deleted inserted replaced
6:c2daee826b8f 7:3fc0f57ecb91
1 /* 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
25 int has_vim = 0; /* installable vim.exe exists */
26 int has_gvim = 0; /* installable gvim.exe exists */
27
28 char oldvimrc[BUFSIZE]; /* name of existing vimrc file */
29 char vimrc[BUFSIZE]; /* name of vimrc file to create */
30
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
38
39 /*
40 * Structure used for each choice the user can make.
41 */
42 struct choice
43 {
44 int active; /* non-zero when choice is active */
45 char *text; /* text displayed for this choice */
46 void (*changefunc)(int idx); /* function to change this choice */
47 int arg; /* argument for function */
48 void (*installfunc)(int idx); /* function to install this choice */
49 };
50
51 struct choice choices[30]; /* choices the user can make */
52 int choice_count = 0; /* number of choices available */
53
54 #define TABLE_SIZE(s) (int)(sizeof(s) / sizeof(*s))
55
56 enum
57 {
58 compat_vi = 1,
59 compat_some_enhancements,
60 compat_all_enhancements
61 };
62 char *(compat_choices[]) =
63 {
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",
68 };
69 int compat_choice = (int)compat_all_enhancements;
70 char *compat_text = "- run Vim %s";
71
72 enum
73 {
74 remap_no = 1,
75 remap_win
76 };
77 char *(remap_choices[]) =
78 {
79 "\nChoose:",
80 "Do not remap keys for Windows behavior",
81 "Remap a few keys for Windows behavior (<C-V>, <C-C>, etc)",
82 };
83 int remap_choice = (int)remap_win;
84 char *remap_text = "- %s";
85
86 enum
87 {
88 mouse_xterm = 1,
89 mouse_mswin
90 };
91 char *(mouse_choices[]) =
92 {
93 "\nChoose the way how Vim uses the mouse:",
94 "right button extends selection (the Unix way)",
95 "right button has a popup menu (the Windows way)",
96 };
97 int mouse_choice = (int)mouse_mswin;
98 char *mouse_text = "- The mouse %s";
99
100 enum
101 {
102 vimfiles_dir_none = 1,
103 vimfiles_dir_vim,
104 vimfiles_dir_home
105 };
106 static char *(vimfiles_dir_choices[]) =
107 {
108 "\nCreate plugin directories:",
109 "No",
110 "In the VIM directory",
111 "In your HOME directory",
112 };
113 static int vimfiles_dir_choice;
114
115 /* non-zero when selected to install the popup menu entry. */
116 static int install_popup = 0;
117
118 /* non-zero when selected to install the "Open with" entry. */
119 static int install_openwith = 0;
120
121 /* non-zero when need to add an uninstall entry in the registry */
122 static int need_uninstall_entry = 0;
123
124 /*
125 * Definitions of the directory name (under $VIM) of the vimfiles directory
126 * and its subdirectories:
127 */
128 static char *(vimfiles_subdirs[]) =
129 {
130 "colors",
131 "compiler",
132 "doc",
133 "ftdetect",
134 "ftplugin",
135 "indent",
136 "keymap",
137 "plugin",
138 "syntax",
139 };
140
141 /*
142 * Copy a directory name from "dir" to "buf", doubling backslashes.
143 * Also make sure it ends in a double backslash.
144 */
145 static void
146 double_bs(char *dir, char *buf)
147 {
148 char *d = buf;
149 char *s;
150
151 for (s = dir; *s; ++s)
152 {
153 if (*s == '\\')
154 *d++ = '\\';
155 *d++ = *s;
156 }
157 /* when dir is not empty, it must end in a double backslash */
158 if (d > buf && d[-1] != '\\')
159 {
160 *d++ = '\\';
161 *d++ = '\\';
162 }
163 *d = NUL;
164 }
165
166 /*
167 * Obtain a choice from a table.
168 * First entry is a question, others are choices.
169 */
170 static int
171 get_choice(char **table, int entries)
172 {
173 int answer;
174 int idx;
175 char dummy[100];
176
177 do
178 {
179 for (idx = 0; idx < entries; ++idx)
180 {
181 if (idx)
182 printf("%2d ", idx);
183 printf(table[idx]);
184 printf("\n");
185 }
186 printf("Choice: ");
187 if (scanf("%d", &answer) != 1)
188 {
189 scanf("%99s", dummy);
190 answer = 0;
191 }
192 }
193 while (answer < 1 || answer >= entries);
194
195 return answer;
196 }
197
198 /*
199 * Check if the user unpacked the archives properly.
200 * Sets "runtimeidx".
201 */
202 static void
203 check_unpack(void)
204 {
205 char buf[BUFSIZE];
206 FILE *fd;
207 struct stat st;
208
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] != '\\'))
215 {
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);
220 }
221
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)
226 {
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);
232 }
233
234 /* Check if vim.exe or gvim.exe is in the current directory. */
235 if ((fd = fopen("gvim.exe", "r")) != NULL)
236 {
237 fclose(fd);
238 has_gvim = 1;
239 }
240 if ((fd = fopen("vim.exe", "r")) != NULL)
241 {
242 fclose(fd);
243 has_vim = 1;
244 }
245 if (!has_gvim && !has_vim)
246 {
247 printf("ERROR: Cannot find any Vim executables in \"%s\"\n\n",
248 installdir);
249 myexit(1);
250 }
251 }
252
253 /*
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.
257 */
258 static int
259 pathcmp(char *p, int plen, char *q, int qlen)
260 {
261 int i;
262
263 if (plen < 0)
264 plen = strlen(p);
265 if (qlen < 0)
266 qlen = strlen(q);
267 for (i = 0; ; ++i)
268 {
269 /* End of "p": check if "q" also ends or just has a slash. */
270 if (i == plen)
271 {
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 */
277 }
278
279 /* End of "q": check if "p" also ends or just has a slash. */
280 if (i == qlen)
281 {
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 */
287 }
288
289 if (!(mytoupper(p[i]) == mytoupper(q[i])
290 || ((p[i] == '/' || p[i] == '\\')
291 && (q[i] == '/' || q[i] == '\\'))))
292 return 1; /* no match */
293 }
294 /*NOTREACHED*/
295 }
296
297 /*
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.
303 */
304 static void
305 findoldfile(char **destination)
306 {
307 char *bp = *destination;
308 size_t indir_l = strlen(installdir);
309 char *cp = bp + indir_l;
310 char *tmpname;
311 char *farname;
312
313 /*
314 * No action needed if exe not found or not in this directory.
315 */
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;
322
323 tmpname = alloc((int)strlen(cp) + 1);
324 strcpy(tmpname, cp);
325 tmpname[strlen(tmpname) - 1] = 'x'; /* .exe -> .exx */
326
327 if (access(tmpname, 0) == 0)
328 {
329 printf("\nERROR: %s and %s clash. Remove or rename %s.\n",
330 tmpname, cp, tmpname);
331 myexit(1);
332 }
333
334 if (rename(cp, tmpname) != 0)
335 {
336 printf("\nERROR: failed to rename %s to %s: %s\n",
337 cp, tmpname, strerror(0));
338 myexit(1);
339 }
340
341 farname = searchpath_save(cp);
342
343 if (rename(tmpname, cp) != 0)
344 {
345 printf("\nERROR: failed to rename %s back to %s: %s\n",
346 tmpname, cp, strerror(0));
347 myexit(1);
348 }
349
350 free(*destination);
351 free(tmpname);
352 *destination = farname;
353 }
354
355 /*
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".
358 */
359 static void
360 find_bat_exe(int check_bat_only)
361 {
362 int i;
363
364 mch_chdir(sysdrive); /* avoid looking in the "installdir" */
365
366 for (i = 1; i < TARGET_COUNT; ++i)
367 {
368 targets[i].oldbat = searchpath_save(targets[i].batname);
369 if (!check_bat_only)
370 targets[i].oldexe = searchpath_save(targets[i].exename);
371
372 if (default_bat_dir == NULL && targets[i].oldbat != NULL)
373 {
374 default_bat_dir = alloc(strlen(targets[i].oldbat) + 1);
375 strcpy(default_bat_dir, targets[i].oldbat);
376 remove_tail(default_bat_dir);
377 }
378 if (check_bat_only && targets[i].oldbat != NULL)
379 free(targets[i].oldbat);
380 }
381
382 mch_chdir(installdir);
383 }
384
385 #ifdef WIN3264
386 /*
387 * Get the value of $VIMRUNTIME or $VIM and write it in $TEMP/vimini.ini, so
388 * that NSIS can read it.
389 * When not set, use the directory of a previously installed Vim.
390 */
391 static void
392 get_vim_env(void)
393 {
394 char *vim;
395 char buf[BUFSIZE];
396 FILE *fd;
397 char fname[BUFSIZE];
398
399 /* First get $VIMRUNTIME. If it's set, remove the tail. */
400 vim = getenv("VIMRUNTIME");
401 if (vim != NULL && *vim != 0)
402 {
403 strcpy(buf, vim);
404 remove_tail(buf);
405 vim = buf;
406 }
407 else
408 {
409 vim = getenv("VIM");
410 if (vim == NULL || *vim == 0)
411 {
412 /* Use the directory from an old uninstall entry. */
413 if (default_vim_dir != NULL)
414 vim = default_vim_dir;
415 else
416 /* Let NSIS know there is no default, it should use
417 * $PROGRAMFIlES. */
418 vim = "";
419 }
420 }
421
422 /* NSIS also uses GetTempPath(), thus we should get the same directory
423 * name as where NSIS will look for vimini.ini. */
424 GetTempPath(BUFSIZE, fname);
425 add_pathsep(fname);
426 strcat(fname, "vimini.ini");
427
428 fd = fopen(fname, "w");
429 if (fd != NULL)
430 {
431 /* Make it look like an .ini file, so that NSIS can read it with a
432 * ReadINIStr command. */
433 fprintf(fd, "[vimini]\n");
434 fprintf(fd, "dir=\"%s\"\n", vim);
435 fclose(fd);
436 }
437 else
438 {
439 printf("Failed to open %s\n", fname);
440 Sleep(2000);
441 }
442 }
443
444 /*
445 * Check for already installed Vims.
446 * Return non-zero when found one.
447 */
448 static int
449 uninstall_check(void)
450 {
451 HKEY key_handle;
452 HKEY uninstall_key_handle;
453 char *uninstall_key = "software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
454 char subkey_name_buff[BUFSIZE];
455 char temp_string_buffer[BUFSIZE];
456 DWORD local_bufsize = BUFSIZE;
457 FILETIME temp_pfiletime;
458 DWORD key_index;
459 char input;
460 long code;
461 DWORD value_type;
462 DWORD orig_num_keys;
463 DWORD new_num_keys;
464 int foundone = 0;
465
466 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0, KEY_READ,
467 &key_handle);
468 CHECK_REG_ERROR(code);
469
470 for (key_index = 0;
471 RegEnumKeyEx(key_handle, key_index, subkey_name_buff, &local_bufsize,
472 NULL, NULL, NULL, &temp_pfiletime) != ERROR_NO_MORE_ITEMS;
473 key_index++)
474 {
475 local_bufsize = BUFSIZE;
476 if (strncmp("Vim", subkey_name_buff, 3) == 0)
477 {
478 /* Open the key named Vim* */
479 code = RegOpenKeyEx(key_handle, subkey_name_buff, 0, KEY_READ,
480 &uninstall_key_handle);
481 CHECK_REG_ERROR(code);
482
483 /* get the DisplayName out of it to show the user */
484 code = RegQueryValueEx(uninstall_key_handle, "displayname", 0,
485 &value_type, (LPBYTE)temp_string_buffer,
486 &local_bufsize);
487 local_bufsize = BUFSIZE;
488 CHECK_REG_ERROR(code);
489
490 foundone = 1;
491 printf("\n*********************************************************\n");
492 printf("Vim Install found what looks like an existing Vim version.\n");
493 printf("The name of the entry is:\n");
494 printf("\n \"%s\"\n\n", temp_string_buffer);
495
496 printf("Installing the new version will disable part of the existing version.\n");
497 printf("(The batch files used in a console and the \"Edit with Vim\" entry in\n");
498 printf("the popup menu will use the new version)\n");
499
500 printf("\nDo you want to uninstall \"%s\" now?\n(y)es/(n)o) ", temp_string_buffer);
501 fflush(stdout);
502
503 /* get the UninstallString */
504 code = RegQueryValueEx(uninstall_key_handle, "uninstallstring", 0,
505 &value_type, (LPBYTE)temp_string_buffer, &local_bufsize);
506 local_bufsize = BUFSIZE;
507 CHECK_REG_ERROR(code);
508
509 /* Remember the directory, it is used as the default for NSIS. */
510 default_vim_dir = alloc(strlen(temp_string_buffer) + 1);
511 strcpy(default_vim_dir, temp_string_buffer);
512 remove_tail(default_vim_dir);
513 remove_tail(default_vim_dir);
514
515 input = 'n';
516 do
517 {
518 if (input != 'n')
519 printf("%c is an invalid reply. Please enter either 'y' or 'n'\n", input);
520
521 rewind(stdin);
522 scanf("%c", &input);
523 switch (input)
524 {
525 case 'y':
526 case 'Y':
527 /* save the number of uninstall keys so we can know if
528 * it changed */
529 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
530 &orig_num_keys, NULL, NULL, NULL,
531 NULL, NULL, NULL, NULL);
532
533 /* Delete the uninstall key. It has no subkeys, so
534 * this is easy. Do this before uninstalling, that
535 * may try to delete the key as well. */
536 RegDeleteKey(key_handle, subkey_name_buff);
537
538 /* Find existing .bat files before deleting them. */
539 find_bat_exe(TRUE);
540
541 /* Execute the uninstall program. Put it in double
542 * quotes if there is an embedded space. */
543 if (strchr(temp_string_buffer, ' ') != NULL)
544 {
545 char buf[BUFSIZE];
546
547 strcpy(buf, temp_string_buffer);
548 sprintf(temp_string_buffer, "\"%s\"", buf);
549 }
550 run_command(temp_string_buffer);
551
552 /* Check if an unistall reg key was deleted.
553 * if it was, we want to decrement key_index.
554 * if we don't do this, we will skip the key
555 * immediately after any key that we delete. */
556 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
557 &new_num_keys, NULL, NULL, NULL,
558 NULL, NULL, NULL, NULL);
559 if (new_num_keys < orig_num_keys)
560 key_index--;
561
562 input = 'y';
563 break;
564
565 case 'n':
566 case 'N':
567 /* Do not uninstall */
568 input = 'n';
569 break;
570
571 default: /* just drop through and redo the loop */
572 break;
573 }
574
575 } while (input != 'n' && input != 'y');
576
577 RegCloseKey(uninstall_key_handle);
578 }
579 }
580 RegCloseKey(key_handle);
581
582 return foundone;
583 }
584 #endif
585
586 /*
587 * Find out information about the system.
588 */
589 static void
590 inspect_system(void)
591 {
592 char *p;
593 char buf[BUFSIZE];
594 FILE *fd;
595 int i;
596 int foundone;
597
598 /* This may take a little while, let the user know what we're doing. */
599 printf("Inspecting system...\n");
600
601 /*
602 * If $VIM is set, check that it's pointing to our directory.
603 */
604 p = getenv("VIM");
605 if (p != NULL && pathcmp(p, -1, installdir, runtimeidx - 1) != 0)
606 {
607 printf("------------------------------------------------------\n");
608 printf("$VIM is set to \"%s\".\n", p);
609 printf("This is different from where this version of Vim is:\n");
610 strcpy(buf, installdir);
611 *(buf + runtimeidx - 1) = NUL;
612 printf("\"%s\"\n", buf);
613 printf("You must adjust or remove the setting of $VIM,\n");
614 if (interactive)
615 {
616 printf("to be able to use this install program.\n");
617 myexit(1);
618 }
619 printf("otherwise Vim WILL NOT WORK properly!\n");
620 printf("------------------------------------------------------\n");
621 }
622
623 /*
624 * If $VIMRUNTIME is set, check that it's pointing to our runtime directory.
625 */
626 p = getenv("VIMRUNTIME");
627 if (p != NULL && pathcmp(p, -1, installdir, -1) != 0)
628 {
629 printf("------------------------------------------------------\n");
630 printf("$VIMRUNTIME is set to \"%s\".\n", p);
631 printf("This is different from where this version of Vim is:\n");
632 printf("\"%s\"\n", installdir);
633 printf("You must adjust or remove the setting of $VIMRUNTIME,\n");
634 if (interactive)
635 {
636 printf("to be able to use this install program.\n");
637 myexit(1);
638 }
639 printf("otherwise Vim WILL NOT WORK properly!\n");
640 printf("------------------------------------------------------\n");
641 }
642
643 /*
644 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
645 */
646 find_bat_exe(FALSE);
647
648 /*
649 * A .exe in the install directory may be found anyway on Windows 2000.
650 * Check for this situation and find another executable if necessary.
651 * w.briscoe@ponl.com 2001-01-20
652 */
653 foundone = 0;
654 for (i = 1; i < TARGET_COUNT; ++i)
655 {
656 findoldfile(&(targets[i].oldexe));
657 if (targets[i].oldexe != NULL)
658 foundone = 1;
659 }
660
661 if (foundone)
662 {
663 printf("Warning: Found Vim executable(s) in your $PATH:\n");
664 for (i = 1; i < TARGET_COUNT; ++i)
665 if (targets[i].oldexe != NULL)
666 printf("%s\n", targets[i].oldexe);
667 printf("It will be used instead of the version you are installing.\n");
668 printf("Please delete or rename it, or adjust your $PATH setting.\n");
669 }
670
671 /*
672 * Check if there is an existing ../_vimrc or ../.vimrc file.
673 */
674 strcpy(oldvimrc, installdir);
675 strcpy(oldvimrc + runtimeidx, "_vimrc");
676 if ((fd = fopen(oldvimrc, "r")) == NULL)
677 {
678 strcpy(oldvimrc + runtimeidx, "vimrc~1"); /* short version of .vimrc */
679 if ((fd = fopen(oldvimrc, "r")) == NULL)
680 {
681 strcpy(oldvimrc + runtimeidx, ".vimrc");
682 fd = fopen(oldvimrc, "r");
683 }
684 }
685 if (fd != NULL)
686 fclose(fd);
687 else
688 *oldvimrc = NUL;
689
690 #if 0 /* currently not used */
691 /*
692 * Get default home directory.
693 * Prefer $HOME if it's set. For Win NT use $HOMEDRIVE and $HOMEPATH.
694 * Otherwise, if there is a "c:" drive use that.
695 */
696 p = getenv("HOME");
697 if (p != NULL && *p != NUL && strlen(p) < BUFSIZE)
698 strcpy(homedir, p);
699 else
700 {
701 p = getenv("HOMEDRIVE");
702 if (p != NULL && *p != NUL && strlen(p) + 2 < BUFSIZE)
703 {
704 strcpy(homedir, p);
705 p = getenv("HOMEPATH");
706 if (p != NULL && *p != NUL && strlen(homedir) + strlen(p) < BUFSIZE)
707 strcat(homedir, p);
708 else
709 strcat(homedir, "\\");
710 }
711 else
712 {
713 struct stat st;
714
715 if (stat("c:\\", &st) == 0)
716 strcpy(homedir, "c:\\");
717 else
718 *homedir = NUL;
719 }
720 }
721 #endif
722 }
723
724 /*
725 * Add a dummy choice to avoid that the numbering changes depending on items
726 * in the environment. The user may type a number he remembered without
727 * looking.
728 */
729 static void
730 add_dummy_choice(void)
731 {
732 choices[choice_count].installfunc = NULL;
733 choices[choice_count].active = 0;
734 choices[choice_count].changefunc = NULL;
735 choices[choice_count].installfunc = NULL;
736 ++choice_count;
737 }
738
739 /***********************************************
740 * stuff for creating the batch files.
741 */
742
743 /*
744 * Install the vim.bat, gvim.bat, etc. files.
745 */
746 static void
747 install_bat_choice(int idx)
748 {
749 char *batpath = targets[choices[idx].arg].batpath;
750 char *oldname = targets[choices[idx].arg].oldbat;
751 char *exename = targets[choices[idx].arg].exenamearg;
752 char *vimarg = targets[choices[idx].arg].exearg;
753 FILE *fd;
754 char buf[BUFSIZE];
755
756 if (*batpath != NUL)
757 {
758 fd = fopen(batpath, "w");
759 if (fd == NULL)
760 printf("\nERROR: Cannot open \"%s\" for writing.\n", batpath);
761 else
762 {
763 need_uninstall_entry = 1;
764
765 fprintf(fd, "@echo off\n");
766 fprintf(fd, "rem -- Run Vim --\n\n");
767
768 strcpy(buf, installdir);
769 buf[runtimeidx - 1] = NUL;
770 /* Don't use double quotes for the value here, also when buf
771 * contains a space. The quotes would be included in the value
772 * for MSDOS and NT. */
773 fprintf(fd, "set VIM=%s\n\n", buf);
774
775 strcpy(buf, installdir + runtimeidx);
776 add_pathsep(buf);
777 strcat(buf, exename);
778
779 /* Give an error message when the executable could not be found. */
780 fprintf(fd, "if exist \"%%VIM%%\\%s\" goto havevim\n", buf);
781 fprintf(fd, "echo \"%%VIM%%\\%s\" not found\n", buf);
782 fprintf(fd, "goto eof\n\n");
783 fprintf(fd, ":havevim\n");
784
785 fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
786 fprintf(fd, "set VIMARGS=\n");
787 if (*exename == 'g')
788 fprintf(fd, "set VIMNOFORK=\n");
789 fprintf(fd, ":loopstart\n");
790 fprintf(fd, "if .%%1==. goto loopend\n");
791 if (*exename == 'g')
792 {
793 fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
794 fprintf(fd, "set VIMNOFORK=1\n");
795 fprintf(fd, ":noforkarg\n");
796 }
797 fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
798 fprintf(fd, "shift\n");
799 fprintf(fd, "goto loopstart\n\n");
800 fprintf(fd, ":loopend\n");
801
802 fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n\n");
803
804 /* For gvim.exe use "start" to avoid that the console window stays
805 * open. */
806 if (*exename == 'g')
807 {
808 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
809 fprintf(fd, "start ");
810 }
811
812 /* Do use quotes here if the path includes a space. */
813 if (strchr(installdir, ' ') != NULL)
814 fprintf(fd, "\"%%VIM%%\\%s\" %s %%VIMARGS%%\n", buf, vimarg);
815 else
816 fprintf(fd, "%%VIM%%\\%s %s %%VIMARGS%%\n", buf, vimarg);
817 fprintf(fd, "goto eof\n\n");
818
819 if (*exename == 'g')
820 {
821 fprintf(fd, ":nofork\n");
822 fprintf(fd, "start /w ");
823 /* Do use quotes here if the path includes a space. */
824 if (strchr(installdir, ' ') != NULL)
825 fprintf(fd, "\"%%VIM%%\\%s\" %s %%VIMARGS%%\n", buf,
826 vimarg);
827 else
828 fprintf(fd, "%%VIM%%\\%s %s %%VIMARGS%%\n", buf, vimarg);
829 fprintf(fd, "goto eof\n\n");
830 }
831
832 fprintf(fd, ":ntaction\n");
833 fprintf(fd, "rem for WinNT we can use %%*\n");
834
835 /* For gvim.exe use "start /b" to avoid that the console window
836 * stays open. */
837 if (*exename == 'g')
838 {
839 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
840 fprintf(fd, "start \"dummy\" /b ");
841 }
842
843 /* Do use quotes here if the path includes a space. */
844 if (strchr(installdir, ' ') != NULL)
845 fprintf(fd, "\"%%VIM%%\\%s\" %s %%*\n", buf, vimarg);
846 else
847 fprintf(fd, "%%VIM%%\\%s %s %%*\n", buf, vimarg);
848 fprintf(fd, "goto eof\n\n");
849
850 if (*exename == 'g')
851 {
852 fprintf(fd, ":noforknt\n");
853 fprintf(fd, "start \"dummy\" /b /wait ");
854 /* Do use quotes here if the path includes a space. */
855 if (strchr(installdir, ' ') != NULL)
856 fprintf(fd, "\"%%VIM%%\\%s\" %s %%*\n", buf, vimarg);
857 else
858 fprintf(fd, "%%VIM%%\\%s %s %%*\n", buf, vimarg);
859 }
860
861 fprintf(fd, "\n:eof\n");
862 fprintf(fd, "set VIMARGS=\n");
863 if (*exename == 'g')
864 fprintf(fd, "set VIMNOFORK=\n");
865
866 fclose(fd);
867 printf("%s has been %s\n", batpath,
868 oldname == NULL ? "created" : "overwritten");
869 }
870 }
871 }
872
873 /*
874 * Make the text string for choice "idx".
875 * The format "fmt" is must have one %s item, which "arg" is used for.
876 */
877 static void
878 alloc_text(int idx, char *fmt, char *arg)
879 {
880 if (choices[idx].text != NULL)
881 free(choices[idx].text);
882
883 choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
884 sprintf(choices[idx].text, fmt, arg);
885 }
886
887 /*
888 * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
889 */
890 static void
891 toggle_bat_choice(int idx)
892 {
893 char *batname = targets[choices[idx].arg].batpath;
894 char *oldname = targets[choices[idx].arg].oldbat;
895
896 if (*batname == NUL)
897 {
898 alloc_text(idx, " Overwrite %s", oldname);
899 strcpy(batname, oldname);
900 }
901 else
902 {
903 alloc_text(idx, " Do NOT overwrite %s", oldname);
904 *batname = NUL;
905 }
906 }
907
908 /*
909 * Do some work for a batch file entry: Append the batch file name to the path
910 * and set the text for the choice.
911 */
912 static void
913 set_bat_text(int idx, char *batpath, char *name)
914 {
915 strcat(batpath, name);
916
917 alloc_text(idx, " Create %s", batpath);
918 }
919
920 /*
921 * Select a directory to write the batch file line.
922 */
923 static void
924 change_bat_choice(int idx)
925 {
926 char *path;
927 char *batpath;
928 char *name;
929 int n;
930 char *s;
931 char *p;
932 int count;
933 char **names = NULL;
934 int i;
935 int target = choices[idx].arg;
936
937 name = targets[target].batname;
938 batpath = targets[target].batpath;
939
940 path = getenv("PATH");
941 if (path == NULL)
942 {
943 printf("\nERROR: The variable $PATH is not set\n");
944 return;
945 }
946
947 /*
948 * first round: count number of names in path;
949 * second round: save names to names[].
950 */
951 for (;;)
952 {
953 count = 1;
954 for (p = path; *p; )
955 {
956 s = strchr(p, ';');
957 if (s == NULL)
958 s = p + strlen(p);
959 if (names != NULL)
960 {
961 names[count] = alloc((int)(s - p) + 1);
962 strncpy(names[count], p, s - p);
963 names[count][s - p] = NUL;
964 }
965 ++count;
966 p = s;
967 if (*p != NUL)
968 ++p;
969 }
970 if (names != NULL)
971 break;
972 names = alloc((int)(count + 1) * sizeof(char *));
973 }
974 names[0] = alloc(50);
975 sprintf(names[0], "Select directory to create %s in:", name);
976 names[count] = alloc(50);
977 if (choices[idx].arg == 0)
978 sprintf(names[count], "Do not create any .bat file.");
979 else
980 sprintf(names[count], "Do not create a %s file.", name);
981 n = get_choice(names, count + 1);
982
983 if (n == count)
984 {
985 /* Selected last item, don't create bat file. */
986 *batpath = NUL;
987 if (choices[idx].arg != 0)
988 alloc_text(idx, " Do NOT create %s", name);
989 }
990 else
991 {
992 /* Selected one of the paths. For the first item only keep the path,
993 * for the others append the batch file name. */
994 strcpy(batpath, names[n]);
995 add_pathsep(batpath);
996 if (choices[idx].arg != 0)
997 set_bat_text(idx, batpath, name);
998 }
999
1000 for (i = 0; i <= count; ++i)
1001 free(names[i]);
1002 free(names);
1003 }
1004
1005 char *bat_text_yes = "Install .bat files to use Vim at the command line:";
1006 char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
1007
1008 static void
1009 change_main_bat_choice(int idx)
1010 {
1011 int i;
1012
1013 /* let the user select a default directory or NONE */
1014 change_bat_choice(idx);
1015
1016 if (targets[0].batpath[0] != NUL)
1017 choices[idx].text = bat_text_yes;
1018 else
1019 choices[idx].text = bat_text_no;
1020
1021 /* update the individual batch file selections */
1022 for (i = 1; i < TARGET_COUNT; ++i)
1023 {
1024 /* Only make it active when the first item has a path and the vim.exe
1025 * or gvim.exe exists (there is a changefunc then). */
1026 if (targets[0].batpath[0] != NUL
1027 && choices[idx + i].changefunc != NULL)
1028 {
1029 choices[idx + i].active = 1;
1030 if (choices[idx + i].changefunc == change_bat_choice
1031 && targets[i].batpath[0] != NUL)
1032 {
1033 strcpy(targets[i].batpath, targets[0].batpath);
1034 set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
1035 }
1036 }
1037 else
1038 choices[idx + i].active = 0;
1039 }
1040 }
1041
1042 /*
1043 * Initialize a choice for creating a batch file.
1044 */
1045 static void
1046 init_bat_choice(int target)
1047 {
1048 char *batpath = targets[target].batpath;
1049 char *oldbat = targets[target].oldbat;
1050 char *p;
1051 int i;
1052
1053 choices[choice_count].arg = target;
1054 choices[choice_count].installfunc = install_bat_choice;
1055 choices[choice_count].active = 1;
1056 choices[choice_count].text = NULL; /* will be set below */
1057 if (oldbat != NULL)
1058 {
1059 /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
1060 choices[choice_count].changefunc = toggle_bat_choice;
1061 *batpath = NUL;
1062 toggle_bat_choice(choice_count);
1063 }
1064 else
1065 {
1066 if (default_bat_dir != NULL)
1067 /* Prefer using the same path as an existing .bat file. */
1068 strcpy(batpath, default_bat_dir);
1069 else
1070 {
1071 /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
1072 * $WINDIR by default, if it's empty the first item in $PATH. */
1073 p = getenv("WINDIR");
1074 if (p != NULL && *p != NUL)
1075 strcpy(batpath, p);
1076 else
1077 {
1078 p = getenv("PATH");
1079 if (p == NULL || *p == NUL) /* "cannot happen" */
1080 strcpy(batpath, "C:/Windows");
1081 else
1082 {
1083 i = 0;
1084 while (*p != NUL && *p != ';')
1085 batpath[i++] = *p++;
1086 batpath[i] = NUL;
1087 }
1088 }
1089 }
1090 add_pathsep(batpath);
1091 set_bat_text(choice_count, batpath, targets[target].batname);
1092
1093 choices[choice_count].changefunc = change_bat_choice;
1094 }
1095 ++choice_count;
1096 }
1097
1098 /*
1099 * Set up the choices for installing .bat files.
1100 * For these items "arg" is the index in targets[].
1101 */
1102 static void
1103 init_bat_choices(void)
1104 {
1105 int i;
1106
1107 /* The first item is used to switch installing batch files on/off and
1108 * setting the default path. */
1109 choices[choice_count].text = bat_text_yes;
1110 choices[choice_count].changefunc = change_main_bat_choice;
1111 choices[choice_count].installfunc = NULL;
1112 choices[choice_count].active = 1;
1113 choices[choice_count].arg = 0;
1114 ++choice_count;
1115
1116 /* Add items for each batch file target. Only used when not disabled by
1117 * the first item. When a .exe exists, don't offer to create a .bat. */
1118 for (i = 1; i < TARGET_COUNT; ++i)
1119 if (targets[i].oldexe == NULL
1120 && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
1121 init_bat_choice(i);
1122 else
1123 add_dummy_choice();
1124 }
1125
1126 /*
1127 * Install the vimrc file.
1128 */
1129 /*ARGSUSED*/
1130 static void
1131 install_vimrc(int idx)
1132 {
1133 FILE *fd, *tfd;
1134 char *fname;
1135 char *p;
1136
1137 /* If an old vimrc file exists, overwrite it.
1138 * Otherwise create a new one. */
1139 if (*oldvimrc != NUL)
1140 fname = oldvimrc;
1141 else
1142 fname = vimrc;
1143
1144 fd = fopen(fname, "w");
1145 if (fd == NULL)
1146 {
1147 printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
1148 return;
1149 }
1150 switch (compat_choice)
1151 {
1152 case compat_vi:
1153 fprintf(fd, "set compatible\n");
1154 break;
1155 case compat_some_enhancements:
1156 fprintf(fd, "set nocompatible\n");
1157 break;
1158 case compat_all_enhancements:
1159 fprintf(fd, "set nocompatible\n");
1160 fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
1161 break;
1162 }
1163 switch (remap_choice)
1164 {
1165 case remap_no:
1166 break;
1167 case remap_win:
1168 fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
1169 break;
1170 }
1171 switch (mouse_choice)
1172 {
1173 case mouse_xterm:
1174 fprintf(fd, "behave xterm\n");
1175 break;
1176 case mouse_mswin:
1177 fprintf(fd, "behave mswin\n");
1178 break;
1179 }
1180 if ((tfd = fopen("diff.exe", "r")) != NULL)
1181 {
1182 /* Use the diff.exe that comes with the self-extracting gvim.exe. */
1183 fclose(tfd);
1184 fprintf(fd, "\n");
1185 fprintf(fd, "set diffexpr=MyDiff()\n");
1186 fprintf(fd, "function MyDiff()\n");
1187 fprintf(fd, " let opt = '-a --binary '\n");
1188 fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
1189 fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
1190 /* Use quotes only when needed, they may cause trouble. */
1191 fprintf(fd, " let arg1 = v:fname_in\n");
1192 fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
1193 fprintf(fd, " let arg2 = v:fname_new\n");
1194 fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
1195 fprintf(fd, " let arg3 = v:fname_out\n");
1196 fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
1197 p = strchr(installdir, ' ');
1198 if (p != NULL)
1199 {
1200 /* The path has a space. When using cmd.exe (Win NT/2000/XP) put
1201 * quotes around the whole command and around the diff command.
1202 * Otherwise put a double quote just before the space and at the
1203 * end of the command. Putting quotes around the whole thing
1204 * doesn't work on Win 95/98/ME. This is mostly guessed! */
1205 fprintf(fd, " if &sh =~ '\\<cmd'\n");
1206 fprintf(fd, " silent execute '!\"\"%s\\diff\" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . '\"'\n", installdir);
1207 fprintf(fd, " else\n");
1208 *p = NUL;
1209 fprintf(fd, " silent execute '!%s\" %s\\diff\" ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n", installdir, p + 1);
1210 *p = ' ';
1211 fprintf(fd, " endif\n");
1212 }
1213 else
1214 fprintf(fd, " silent execute '!%s\\diff ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n", installdir);
1215 fprintf(fd, "endfunction\n");
1216 fprintf(fd, "\n");
1217 }
1218 fclose(fd);
1219 printf("%s has been written\n", fname);
1220 }
1221
1222 static void
1223 change_vimrc_choice(int idx)
1224 {
1225 if (choices[idx].installfunc != NULL)
1226 {
1227 /* Switch to NOT change or create a vimrc file. */
1228 if (*oldvimrc != NUL)
1229 alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
1230 else
1231 alloc_text(idx, "Do NOT create startup file %s", vimrc);
1232 choices[idx].installfunc = NULL;
1233 choices[idx + 1].active = 0;
1234 choices[idx + 2].active = 0;
1235 choices[idx + 3].active = 0;
1236 }
1237 else
1238 {
1239 /* Switch to change or create a vimrc file. */
1240 if (*oldvimrc != NUL)
1241 alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
1242 else
1243 alloc_text(idx, "Create startup file %s with:", vimrc);
1244 choices[idx].installfunc = install_vimrc;
1245 choices[idx + 1].active = 1;
1246 choices[idx + 2].active = 1;
1247 choices[idx + 3].active = 1;
1248 }
1249 }
1250
1251 /*
1252 * Change the choice how to run Vim.
1253 */
1254 static void
1255 change_run_choice(int idx)
1256 {
1257 compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
1258 alloc_text(idx, compat_text, compat_choices[compat_choice]);
1259 }
1260
1261 /*
1262 * Change the choice if keys are to be remapped.
1263 */
1264 static void
1265 change_remap_choice(int idx)
1266 {
1267 remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
1268 alloc_text(idx, remap_text, remap_choices[remap_choice]);
1269 }
1270
1271 /*
1272 * Change the choice how to select text.
1273 */
1274 static void
1275 change_mouse_choice(int idx)
1276 {
1277 mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
1278 alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
1279 }
1280
1281 static void
1282 init_vimrc_choices(void)
1283 {
1284 /* set path for a new _vimrc file (also when not used) */
1285 strcpy(vimrc, installdir);
1286 strcpy(vimrc + runtimeidx, "_vimrc");
1287
1288 /* Set opposite value and then toggle it by calling change_vimrc_choice() */
1289 if (*oldvimrc == NUL)
1290 choices[choice_count].installfunc = NULL;
1291 else
1292 choices[choice_count].installfunc = install_vimrc;
1293 choices[choice_count].text = NULL;
1294 change_vimrc_choice(choice_count);
1295 choices[choice_count].changefunc = change_vimrc_choice;
1296 choices[choice_count].active = 1;
1297 ++choice_count;
1298
1299 /* default way to run Vim */
1300 alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
1301 choices[choice_count].changefunc = change_run_choice;
1302 choices[choice_count].installfunc = NULL;
1303 choices[choice_count].active = (*oldvimrc == NUL);
1304 ++choice_count;
1305
1306 /* Whether to remap keys */
1307 alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
1308 choices[choice_count].changefunc = change_remap_choice;
1309 choices[choice_count].installfunc = NULL;;
1310 choices[choice_count].active = (*oldvimrc == NUL);
1311 ++choice_count;
1312
1313 /* default way to use the mouse */
1314 alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
1315 choices[choice_count].changefunc = change_mouse_choice;
1316 choices[choice_count].installfunc = NULL;;
1317 choices[choice_count].active = (*oldvimrc == NUL);
1318 ++choice_count;
1319 }
1320
1321 /*
1322 * Add some entries to the registry:
1323 * - to add "Edit with Vim" to the context * menu
1324 * - to add Vim to the "Open with..." list
1325 * - to uninstall Vim
1326 */
1327 /*ARGSUSED*/
1328 static void
1329 install_registry(void)
1330 {
1331 #if defined(DJGPP) || defined(WIN3264) || defined(UNIX_LINT)
1332 FILE *fd;
1333 const char *vim_ext_ThreadingModel = "Apartment";
1334 const char *vim_ext_name = "Vim Shell Extension";
1335 const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
1336 char buf[BUFSIZE];
1337
1338 fd = fopen("vim.reg", "w");
1339 if (fd == NULL)
1340 printf("ERROR: Could not open vim.reg for writing\n");
1341 else
1342 {
1343 double_bs(installdir, buf); /* double the backslashes */
1344
1345 /*
1346 * Write the registry entries for the "Edit with Vim" menu.
1347 */
1348 fprintf(fd, "REGEDIT4\n");
1349 fprintf(fd, "\n");
1350 if (install_popup)
1351 {
1352 char bufg[BUFSIZE];
1353 struct stat st;
1354
1355 if (stat("gvimext.dll", &st) >= 0)
1356 strcpy(bufg, buf);
1357 else
1358 /* gvimext.dll is in gvimext subdir */
1359 sprintf(bufg, "%sgvimext\\\\", buf);
1360
1361 printf("Creating \"Edit with Vim\" popup menu entry\n");
1362
1363 fprintf(fd, "HKEY_CLASSES_ROOT\\CLSID\\%s\n", vim_ext_clsid);
1364 fprintf(fd, "@=\"%s\"\n", vim_ext_name);
1365 fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\%s\\InProcServer32]\n",
1366 vim_ext_clsid);
1367 fprintf(fd, "@=\"%sgvimext.dll\"\n", bufg);
1368 fprintf(fd, "\"ThreadingModel\"=\"%s\"\n", vim_ext_ThreadingModel);
1369 fprintf(fd, "\n");
1370 fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\shellex\\ContextMenuHandlers\\gvim]\n");
1371 fprintf(fd, "@=\"%s\"\n", vim_ext_clsid);
1372 fprintf(fd, "\n");
1373 fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved]\n");
1374 fprintf(fd, "\"%s\"=\"%s\"\n", vim_ext_clsid, vim_ext_name);
1375 fprintf(fd, "\n");
1376 fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Vim\\Gvim]\n");
1377 fprintf(fd, "\"path\"=\"%sgvim.exe\"\n", buf);
1378 fprintf(fd, "\n");
1379 }
1380
1381 if (install_openwith)
1382 {
1383 printf("Creating \"Open with ...\" list entry\n");
1384
1385 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe]\n\n");
1386 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell]\n\n");
1387 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell\\edit]\n\n");
1388 fprintf(fd, "[HKEY_CLASSES_ROOT\\Applications\\gvim.exe\\shell\\edit\\command]\n");
1389 fprintf(fd, "@=\"%sgvim.exe \\\"%%1\\\"\"\n\n", buf);
1390 fprintf(fd, "[HKEY_CLASSES_ROOT\\.htm\\OpenWithList\\gvim.exe]\n\n");
1391 fprintf(fd, "[HKEY_CLASSES_ROOT\\.vim\\OpenWithList\\gvim.exe]\n\n");
1392 fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\OpenWithList\\gvim.exe]\n\n");
1393 }
1394
1395 printf("Creating an uninstall entry\n");
1396
1397 /* The registry entries for uninstalling the menu */
1398 fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT "]\n");
1399
1400 /* For the NSIS installer use the generated uninstaller. */
1401 if (interactive)
1402 {
1403 fprintf(fd, "\"DisplayName\"=\"Vim " VIM_VERSION_SHORT "\"\n");
1404 fprintf(fd, "\"UninstallString\"=\"%suninstal.exe\"\n", buf);
1405 }
1406 else
1407 {
1408 fprintf(fd, "\"DisplayName\"=\"Vim " VIM_VERSION_SHORT " (self-installing)\"\n");
1409 fprintf(fd, "\"UninstallString\"=\"%suninstall-gui.exe\"\n", buf);
1410 }
1411
1412 fclose(fd);
1413
1414 run_command("regedit /s vim.reg");
1415
1416 remove("vim.reg");
1417 }
1418 #endif /* if defined(DJGPP) || defined(WIN3264) */
1419 }
1420
1421 static void
1422 change_popup_choice(int idx)
1423 {
1424 if (install_popup == 0)
1425 {
1426 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";
1427 install_popup = 1;
1428 }
1429 else
1430 {
1431 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";
1432 install_popup = 0;
1433 }
1434 }
1435
1436 /*
1437 * Only add the choice for the popup menu entry when gvim.exe was found and
1438 * both gvimext.dll and regedit.exe exist.
1439 */
1440 static void
1441 init_popup_choice(void)
1442 {
1443 struct stat st;
1444
1445 if (has_gvim
1446 && (stat("gvimext.dll", &st) >= 0
1447 || stat("gvimext/gvimext.dll", &st) >= 0)
1448 #ifndef WIN3264
1449 && searchpath("regedit.exe") != NULL
1450 #endif
1451 )
1452 {
1453 choices[choice_count].changefunc = change_popup_choice;
1454 choices[choice_count].installfunc = NULL;
1455 choices[choice_count].active = 1;
1456 change_popup_choice(choice_count); /* set the text */
1457 ++choice_count;
1458 }
1459 else
1460 add_dummy_choice();
1461 }
1462
1463 static void
1464 change_openwith_choice(int idx)
1465 {
1466 if (install_openwith == 0)
1467 {
1468 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";
1469 install_openwith = 1;
1470 }
1471 else
1472 {
1473 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";
1474 install_openwith = 0;
1475 }
1476 }
1477
1478 /*
1479 * Only add the choice for the open-with menu entry when gvim.exe was found
1480 * and and regedit.exe exist.
1481 */
1482 static void
1483 init_openwith_choice(void)
1484 {
1485 if (has_gvim
1486 #ifndef WIN3264
1487 && searchpath("regedit.exe") != NULL
1488 #endif
1489 )
1490 {
1491 choices[choice_count].changefunc = change_openwith_choice;
1492 choices[choice_count].installfunc = NULL;
1493 choices[choice_count].active = 1;
1494 change_openwith_choice(choice_count); /* set the text */
1495 ++choice_count;
1496 }
1497 else
1498 add_dummy_choice();
1499 }
1500
1501 #ifdef WIN3264
1502 /* create_shortcut
1503 *
1504 * Create a shell link.
1505 *
1506 * returns 0 on failure, non-zero on successful completion.
1507 *
1508 * NOTE: Currently untested with mingw.
1509 */
1510 int
1511 create_shortcut(
1512 const char *shortcut_name,
1513 const char *iconfile_path,
1514 int iconindex,
1515 const char *shortcut_target,
1516 const char *shortcut_args,
1517 const char *workingdir
1518 )
1519 {
1520 IShellLink *shelllink_ptr;
1521 HRESULT hres;
1522 IPersistFile *persistfile_ptr;
1523
1524 /* Initialize COM library */
1525 hres = CoInitialize(NULL);
1526 if (!SUCCEEDED(hres))
1527 {
1528 printf("Error: Could not open the COM library. Not creating shortcut.\n");
1529 return FAIL;
1530 }
1531
1532 /* Instantiate a COM object for the ShellLink, store a pointer to it
1533 * in shelllink_ptr. */
1534 hres = CoCreateInstance(&CLSID_ShellLink,
1535 NULL,
1536 CLSCTX_INPROC_SERVER,
1537 &IID_IShellLink,
1538 (void **) &shelllink_ptr);
1539
1540 if (SUCCEEDED(hres)) /* If the instantiation was successful... */
1541 {
1542 /* ...Then build a PersistFile interface for the ShellLink so we can
1543 * save it as a file after we build it. */
1544 hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
1545 &IID_IPersistFile, (void **) &persistfile_ptr);
1546
1547 if (SUCCEEDED(hres))
1548 {
1549 wchar_t wsz[BUFSIZE];
1550
1551 /* translate the (possibly) multibyte shortcut filename to windows
1552 * Unicode so it can be used as a file name.
1553 */
1554 MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
1555
1556 /* set the attributes */
1557 shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
1558 shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
1559 workingdir);
1560 shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
1561 iconfile_path, iconindex);
1562 shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
1563
1564 /* save the shortcut to a file and return the PersistFile object*/
1565 persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
1566 persistfile_ptr->lpVtbl->Release(persistfile_ptr);
1567 }
1568 else
1569 {
1570 printf("QueryInterface Error\n");
1571 return FAIL;
1572 }
1573
1574 /* Return the ShellLink object */
1575 shelllink_ptr->lpVtbl->Release(shelllink_ptr);
1576 }
1577 else
1578 {
1579 printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
1580 return FAIL;
1581 }
1582
1583 return OK;
1584 }
1585
1586 /*
1587 * Build a path to where we will put a specified link.
1588 *
1589 * Return 0 on error, non-zero on success
1590 */
1591 int
1592 build_link_name(
1593 char *link_path,
1594 const char *link_name,
1595 const char *shell_folder_name)
1596 {
1597 char shell_folder_path[BUFSIZE];
1598
1599 if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
1600 {
1601 printf("An error occurred while attempting to find the path to %s.\n",
1602 shell_folder_name);
1603 return FAIL;
1604 }
1605
1606 /* Make sure the directory exists (create Start Menu\Programs\Vim).
1607 * Ignore errors if it already exists. */
1608 vim_mkdir(shell_folder_path, 0755);
1609
1610 /* build the path to the shortcut and the path to gvim.exe */
1611 sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
1612
1613 return OK;
1614 }
1615
1616 static int
1617 build_shortcut(
1618 const char *name, /* Name of the shortcut */
1619 const char *exename, /* Name of the executable (e.g., vim.exe) */
1620 const char *args,
1621 const char *shell_folder,
1622 const char *workingdir)
1623 {
1624 char executable_path[BUFSIZE];
1625 char link_name[BUFSIZE];
1626
1627 sprintf(executable_path, "%s\\%s", installdir, exename);
1628
1629 if (build_link_name(link_name, name, shell_folder) == FAIL)
1630 {
1631 printf("An error has occurred. A shortcut to %s will not be created %s.\n",
1632 name,
1633 *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
1634 return FAIL;
1635 }
1636
1637 /* Create the shortcut: */
1638 return create_shortcut(link_name, executable_path, 0,
1639 executable_path, args, workingdir);
1640 }
1641
1642 /*
1643 * We used to use "homedir" as the working directory, but that is a bad choice
1644 * on multi-user systems. Not specifying a directory appears to work best.
1645 */
1646 #define WORKDIR ""
1647
1648 /*
1649 * Create shortcut(s) in the Start Menu\Programs\Vim folder.
1650 */
1651 static void
1652 install_start_menu(int idx)
1653 {
1654 need_uninstall_entry = 1;
1655 printf("Creating start menu\n");
1656 if (has_vim)
1657 {
1658 if (build_shortcut("Vim", "vim.exe", "",
1659 VIM_STARTMENU, WORKDIR) == FAIL)
1660 return;
1661 if (build_shortcut("Vim Read-only", "vim.exe", "-R",
1662 VIM_STARTMENU, WORKDIR) == FAIL)
1663 return;
1664 if (build_shortcut("Vim Diff", "vim.exe", "-d",
1665 VIM_STARTMENU, WORKDIR) == FAIL)
1666 return;
1667 }
1668 if (has_gvim)
1669 {
1670 if (build_shortcut("gVim", "gvim.exe", "",
1671 VIM_STARTMENU, WORKDIR) == FAIL)
1672 return;
1673 if (build_shortcut("gVim Easy", "gvim.exe", "-y",
1674 VIM_STARTMENU, WORKDIR) == FAIL)
1675 return;
1676 if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
1677 VIM_STARTMENU, WORKDIR) == FAIL)
1678 return;
1679 if (build_shortcut("gVim Diff", "gvim.exe", "-d",
1680 VIM_STARTMENU, WORKDIR) == FAIL)
1681 return;
1682 }
1683 if (build_shortcut("Uninstall",
1684 interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
1685 VIM_STARTMENU, installdir) == FAIL)
1686 return;
1687 /* For Windows NT the working dir of the vimtutor.bat must be right,
1688 * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
1689 if (build_shortcut("Vim tutor", "vimtutor.bat", "",
1690 VIM_STARTMENU, installdir) == FAIL)
1691 return;
1692 if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
1693 VIM_STARTMENU, WORKDIR) == FAIL)
1694 return;
1695 {
1696 char shell_folder_path[BUFSIZE];
1697
1698 /* Creating the URL shortcut works a bit differently... */
1699 if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
1700 {
1701 printf("Finding the path of the Start menu failed\n");
1702 return ;
1703 }
1704 add_pathsep(shell_folder_path);
1705 strcat(shell_folder_path, "Vim Online.url");
1706 if (!WritePrivateProfileString("InternetShortcut", "URL",
1707 "http://vim.sf.net/", shell_folder_path))
1708 {
1709 printf("Creating the Vim online URL failed\n");
1710 return;
1711 }
1712 }
1713 }
1714
1715 static void
1716 toggle_startmenu_choice(int idx)
1717 {
1718 if (choices[idx].installfunc == NULL)
1719 {
1720 choices[idx].installfunc = install_start_menu;
1721 choices[idx].text = "Add Vim to the Start menu";
1722 }
1723 else
1724 {
1725 choices[idx].installfunc = NULL;
1726 choices[idx].text = "Do NOT add Vim to the Start menu";
1727 }
1728 }
1729
1730 /*
1731 * Function to actually create the shortcuts
1732 *
1733 * Currently I am supplying no working directory to the shortcut. This
1734 * means that the initial working dir will be:
1735 * - the location of the shortcut if no file is supplied
1736 * - the location of the file being edited if a file is supplied (ie via
1737 * drag and drop onto the shortcut).
1738 */
1739 void
1740 install_shortcut_gvim(int idx)
1741 {
1742 /* Create shortcut(s) on the desktop */
1743 if (choices[idx].arg)
1744 {
1745 (void)build_shortcut(icon_names[0], "gvim.exe",
1746 "", "desktop", WORKDIR);
1747 need_uninstall_entry = 1;
1748 }
1749 }
1750
1751 void
1752 install_shortcut_evim(int idx)
1753 {
1754 if (choices[idx].arg)
1755 {
1756 (void)build_shortcut(icon_names[1], "gvim.exe",
1757 "-y", "desktop", WORKDIR);
1758 need_uninstall_entry = 1;
1759 }
1760 }
1761
1762 void
1763 install_shortcut_gview(int idx)
1764 {
1765 if (choices[idx].arg)
1766 {
1767 (void)build_shortcut(icon_names[2], "gvim.exe",
1768 "-R", "desktop", WORKDIR);
1769 need_uninstall_entry = 1;
1770 }
1771 }
1772
1773 void
1774 toggle_shortcut_choice(int idx)
1775 {
1776 char *arg;
1777
1778 if (choices[idx].installfunc == install_shortcut_gvim)
1779 arg = "gVim";
1780 else if (choices[idx].installfunc == install_shortcut_evim)
1781 arg = "gVim Easy";
1782 else
1783 arg = "gVim Read-only";
1784 if (choices[idx].arg)
1785 {
1786 choices[idx].arg = 0;
1787 alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
1788 }
1789 else
1790 {
1791 choices[idx].arg = 1;
1792 alloc_text(idx, "Create a desktop icon for %s", arg);
1793 }
1794 }
1795 #endif /* WIN3264 */
1796
1797 static void
1798 init_startmenu_choice(void)
1799 {
1800 #ifdef WIN3264
1801 /* Start menu */
1802 choices[choice_count].changefunc = toggle_startmenu_choice;
1803 choices[choice_count].installfunc = NULL;
1804 choices[choice_count].active = 1;
1805 toggle_startmenu_choice(choice_count); /* set the text */
1806 ++choice_count;
1807 #else
1808 add_dummy_choice();
1809 #endif
1810 }
1811
1812 /*
1813 * Add the choice for the desktop shortcuts.
1814 */
1815 static void
1816 init_shortcut_choices(void)
1817 {
1818 #ifdef WIN3264
1819 /* Shortcut to gvim */
1820 choices[choice_count].text = NULL;
1821 choices[choice_count].arg = 0;
1822 choices[choice_count].active = has_gvim;
1823 choices[choice_count].changefunc = toggle_shortcut_choice;
1824 choices[choice_count].installfunc = install_shortcut_gvim;
1825 toggle_shortcut_choice(choice_count);
1826 ++choice_count;
1827
1828 /* Shortcut to evim */
1829 choices[choice_count].text = NULL;
1830 choices[choice_count].arg = 0;
1831 choices[choice_count].active = has_gvim;
1832 choices[choice_count].changefunc = toggle_shortcut_choice;
1833 choices[choice_count].installfunc = install_shortcut_evim;
1834 toggle_shortcut_choice(choice_count);
1835 ++choice_count;
1836
1837 /* Shortcut to gview */
1838 choices[choice_count].text = NULL;
1839 choices[choice_count].arg = 0;
1840 choices[choice_count].active = has_gvim;
1841 choices[choice_count].changefunc = toggle_shortcut_choice;
1842 choices[choice_count].installfunc = install_shortcut_gview;
1843 toggle_shortcut_choice(choice_count);
1844 ++choice_count;
1845 #else
1846 add_dummy_choice();
1847 add_dummy_choice();
1848 add_dummy_choice();
1849 #endif
1850 }
1851
1852 #ifdef WIN3264
1853 /*
1854 * Attempt to register OLE for Vim.
1855 */
1856 static void
1857 install_OLE_register(void)
1858 {
1859 char register_command_string[BUFSIZE + 30];
1860
1861 printf("\n--- Attempting to register Vim with OLE ---\n");
1862 printf("(There is no message whether this works or not.)\n");
1863
1864 #ifndef __CYGWIN__
1865 sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
1866 #else
1867 /* handle this differently for Cygwin which sometimes has trouble with
1868 * Windows-style pathnames here. */
1869 sprintf(register_command_string, "./gvim.exe -silent -register");
1870 #endif
1871 system(register_command_string);
1872 }
1873 #endif /* WIN3264 */
1874
1875 /*
1876 * Remove the last part of directory "path[]" to get its parent, and put the
1877 * result in "to[]".
1878 */
1879 static void
1880 dir_remove_last(const char *path, char to[BUFSIZE])
1881 {
1882 char c;
1883 long last_char_to_copy;
1884 long path_length = strlen(path);
1885
1886 /* skip the last character just in case it is a '\\' */
1887 last_char_to_copy = path_length - 2;
1888 c = path[last_char_to_copy];
1889
1890 while (c != '\\')
1891 {
1892 last_char_to_copy--;
1893 c = path[last_char_to_copy];
1894 }
1895
1896 strncpy(to, path, (size_t)last_char_to_copy);
1897 to[last_char_to_copy] = NUL;
1898 }
1899
1900 static void
1901 set_directories_text(int idx)
1902 {
1903 if (vimfiles_dir_choice == (int)vimfiles_dir_none)
1904 alloc_text(idx, "Do NOT create plugin directories%s", "");
1905 else
1906 alloc_text(idx, "Create plugin directories: %s",
1907 vimfiles_dir_choices[vimfiles_dir_choice]);
1908 }
1909
1910 /*
1911 * Change the directory that the vim plugin directories will be created in:
1912 * $HOME, $VIM or nowhere.
1913 */
1914 static void
1915 change_directories_choice(int idx)
1916 {
1917 int choice_count = TABLE_SIZE(vimfiles_dir_choices);
1918
1919 /* Don't offer the $HOME choice if $HOME isn't set. */
1920 if (getenv("HOME") == NULL)
1921 --choice_count;
1922 vimfiles_dir_choice = get_choice(vimfiles_dir_choices, choice_count);
1923 set_directories_text(idx);
1924 }
1925
1926 /*
1927 * Create the plugin directories...
1928 */
1929 /*ARGSUSED*/
1930 static void
1931 install_vimfilesdir(int idx)
1932 {
1933 int i;
1934 char *p;
1935 char vimdir_path[BUFSIZE];
1936 char vimfiles_path[BUFSIZE];
1937 char tmp_dirname[BUFSIZE];
1938
1939 /* switch on the location that the user wants the plugin directories
1940 * built in */
1941 switch (vimfiles_dir_choice)
1942 {
1943 case vimfiles_dir_vim:
1944 {
1945 /* Go to the %VIM% directory - check env first, then go one dir
1946 * below installdir if there is no %VIM% environment variable.
1947 * The accuracy of $VIM is checked in inspect_system(), so we
1948 * can be sure it is ok to use here. */
1949 p = getenv("VIM");
1950 if (p == NULL) /* No $VIM in path */
1951 dir_remove_last(installdir, vimdir_path);
1952 else
1953 strcpy(vimdir_path, p);
1954 break;
1955 }
1956 case vimfiles_dir_home:
1957 {
1958 /* Find the $HOME directory. Its existence was already checked. */
1959 p = getenv("HOME");
1960 if (p == NULL)
1961 {
1962 printf("Internal error: $HOME is NULL\n");
1963 p = "c:\\";
1964 }
1965 strcpy(vimdir_path, p);
1966 break;
1967 }
1968 case vimfiles_dir_none:
1969 {
1970 /* Do not create vim plugin directory */
1971 return;
1972 }
1973 }
1974
1975 /* Now, just create the directory. If it already exists, it will fail
1976 * silently. */
1977 sprintf(vimfiles_path, "%s\\vimfiles", vimdir_path);
1978 vim_mkdir(vimfiles_path, 0755);
1979
1980 printf("Creating the following directories in \"%s\":\n", vimfiles_path);
1981 for (i = 0; i < TABLE_SIZE(vimfiles_subdirs); i++)
1982 {
1983 sprintf(tmp_dirname, "%s\\%s", vimfiles_path, vimfiles_subdirs[i]);
1984 printf(" %s", vimfiles_subdirs[i]);
1985 vim_mkdir(tmp_dirname, 0755);
1986 }
1987 printf("\n");
1988 }
1989
1990 /*
1991 * Add the creation of runtime files to the setup sequence.
1992 */
1993 static void
1994 init_directories_choice(void)
1995 {
1996 struct stat st;
1997 char tmp_dirname[BUFSIZE];
1998 char *p;
1999
2000 choices[choice_count].text = alloc(150);
2001 choices[choice_count].changefunc = change_directories_choice;
2002 choices[choice_count].installfunc = install_vimfilesdir;
2003 choices[choice_count].active = 1;
2004
2005 /* Check if the "compiler" directory already exists. That's a good
2006 * indication that the plugin directories were already created. */
2007 if (getenv("HOME") != NULL)
2008 {
2009 vimfiles_dir_choice = (int)vimfiles_dir_home;
2010 sprintf(tmp_dirname, "%s\\vimfiles\\compiler", getenv("HOME"));
2011 if (stat(tmp_dirname, &st) == 0)
2012 vimfiles_dir_choice = (int)vimfiles_dir_none;
2013 }
2014 else
2015 {
2016 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2017 p = getenv("VIM");
2018 if (p == NULL) /* No $VIM in path, use the install dir */
2019 dir_remove_last(installdir, tmp_dirname);
2020 else
2021 strcpy(tmp_dirname, p);
2022 strcat(tmp_dirname, "\\vimfiles\\compiler");
2023 if (stat(tmp_dirname, &st) == 0)
2024 vimfiles_dir_choice = (int)vimfiles_dir_none;
2025 }
2026
2027 set_directories_text(choice_count);
2028 ++choice_count;
2029 }
2030
2031 /*
2032 * Setup the choices and the default values.
2033 */
2034 static void
2035 setup_choices(void)
2036 {
2037 /* install the batch files */
2038 init_bat_choices();
2039
2040 /* (over) write _vimrc file */
2041 init_vimrc_choices();
2042
2043 /* Whether to add Vim to the popup menu */
2044 init_popup_choice();
2045
2046 /* Whether to add Vim to the "Open With..." menu */
2047 init_openwith_choice();
2048
2049 /* Whether to add Vim to the Start Menu. */
2050 init_startmenu_choice();
2051
2052 /* Whether to add shortcuts to the Desktop. */
2053 init_shortcut_choices();
2054
2055 /* Whether to create the runtime directories. */
2056 init_directories_choice();
2057 }
2058
2059 static void
2060 print_cmd_line_help(void)
2061 {
2062 printf("Vim installer non-interactive command line arguments:\n");
2063 printf("\n");
2064 printf("-create-batfiles [vim gvim evim view gview vimdiff gvimdiff]\n");
2065 printf(" Create .bat files for Vim variants in the Windows directory.\n");
2066 printf("-create-vimrc\n");
2067 printf(" Create a default _vimrc file if one does not already exist.\n");
2068 printf("-install-popup\n");
2069 printf(" Install the Edit-with-Vim context menu entry\n");
2070 printf("-install-openwith\n");
2071 printf(" Add Vim to the \"Open With...\" context menu list\n");
2072 #ifdef WIN3264
2073 printf("-add-start-menu");
2074 printf(" Add Vim to the start menu\n");
2075 printf("-install-icons");
2076 printf(" Create icons for gVim executables on the desktop\n");
2077 #endif
2078 printf("-create-directories [vim|home]\n");
2079 printf(" Create runtime directories to drop plugins into; in the $VIM\n");
2080 printf(" or $HOME directory\n");
2081 #ifdef WIN3264
2082 printf("-register-OLE");
2083 printf(" Register gvim for OLE\n");
2084 #endif
2085 printf("\n");
2086 }
2087
2088 /*
2089 * Setup installation choices based on command line switches
2090 */
2091 static void
2092 command_line_setup_choices(int argc, char **argv)
2093 {
2094 int i, j;
2095
2096 for (i = 1; i < argc; i++)
2097 {
2098 if (strcmp(argv[i], "-create-batfiles") == 0)
2099 {
2100 if (i + 1 == argc)
2101 continue;
2102 while (argv[i + 1][0] != '-' && i < argc)
2103 {
2104 i++;
2105 for (j = 1; j < TARGET_COUNT; ++j)
2106 if ((targets[j].exenamearg[0] == 'g' ? has_gvim : has_vim)
2107 && strcmp(argv[i], targets[j].name) == 0)
2108 {
2109 init_bat_choice(j);
2110 break;
2111 }
2112 if (j == TARGET_COUNT)
2113 printf("%s is not a valid choice for -create-batfiles\n",
2114 argv[i]);
2115
2116 if (i + 1 == argc)
2117 break;
2118 }
2119 }
2120 else if (strcmp(argv[i], "-create-vimrc") == 0)
2121 {
2122 /* Setup default vimrc choices. If there is already a _vimrc file,
2123 * it will NOT be overwritten.
2124 */
2125 init_vimrc_choices();
2126 }
2127 else if (strcmp(argv[i], "-install-popup") == 0)
2128 {
2129 init_popup_choice();
2130 }
2131 else if (strcmp(argv[i], "-install-openwith") == 0)
2132 {
2133 init_openwith_choice();
2134 }
2135 else if (strcmp(argv[i], "-add-start-menu") == 0)
2136 {
2137 init_startmenu_choice();
2138 }
2139 else if (strcmp(argv[i], "-install-icons") == 0)
2140 {
2141 init_shortcut_choices();
2142 }
2143 else if (strcmp(argv[i], "-create-directories") == 0)
2144 {
2145 init_directories_choice();
2146 if (argv[i + 1][0] != '-')
2147 {
2148 i++;
2149 if (strcmp(argv[i], "vim") == 0)
2150 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2151 else if (strcmp(argv[i], "home") == 0)
2152 {
2153 if (getenv("HOME") == NULL) /* No $HOME in environment */
2154 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2155 else
2156 vimfiles_dir_choice = (int)vimfiles_dir_home;
2157 }
2158 else
2159 {
2160 printf("Unknown argument for -create-directories: %s\n",
2161 argv[i]);
2162 print_cmd_line_help();
2163 }
2164 }
2165 else /* No choice specified, default to vim directory */
2166 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2167 }
2168 #ifdef WIN3264
2169 else if (strcmp(argv[i], "-register-OLE") == 0)
2170 {
2171 /* This is always done when gvim is found */
2172 }
2173 #endif
2174 else /* Unknown switch */
2175 {
2176 printf("Got unknown argument argv[%d] = %s\n", i, argv[i]);
2177 print_cmd_line_help();
2178 }
2179 }
2180 }
2181
2182
2183 /*
2184 * Show a few screens full of helpful information.
2185 */
2186 static void
2187 show_help(void)
2188 {
2189 static char *(items[]) =
2190 {
2191 "Installing .bat files\n"
2192 "---------------------\n"
2193 "The vim.bat file is written in one of the directories in $PATH.\n"
2194 "This makes it possible to start Vim from the command line.\n"
2195 "If vim.exe can be found in $PATH, the choice for vim.bat will not be\n"
2196 "present. It is assumed you will use the existing vim.exe.\n"
2197 "If vim.bat can already be found in $PATH this is probably for an old\n"
2198 "version of Vim (but this is not checked!). You can overwrite it.\n"
2199 "If no vim.bat already exists, you can select one of the directories in\n"
2200 "$PATH for creating the batch file, or disable creating a vim.bat file.\n"
2201 "\n"
2202 "If you choose not to create the vim.bat file, Vim can still be executed\n"
2203 "in other ways, but not from the command line.\n"
2204 "\n"
2205 "The same applies to choices for gvim, evim, (g)view, and (g)vimdiff.\n"
2206 "The first item can be used to change the path for all of them.\n"
2207 ,
2208 "Creating a _vimrc file\n"
2209 "----------------------\n"
2210 "The _vimrc file is used to set options for how Vim behaves.\n"
2211 "The install program can create a _vimrc file with a few basic choices.\n"
2212 "You can edit this file later to tune your preferences.\n"
2213 "If you already have a _vimrc or .vimrc file it can be overwritten.\n"
2214 "Don't do that if you have made changes to it.\n"
2215 ,
2216 "Vim features\n"
2217 "------------\n"
2218 "(this choice is only available when creating a _vimrc file)\n"
2219 "1. Vim can run in Vi-compatible mode. Many nice Vim features are then\n"
2220 " disabled. In the not-Vi-compatible mode Vim is still mostly Vi\n"
2221 " compatible, but adds nice features like multi-level undo. Only\n"
2222 " choose Vi-compatible if you really need full Vi compatibility.\n"
2223 "2. Running Vim with some enhancements is useful when you want some of\n"
2224 " the nice Vim features, but have a slow computer and want to keep it\n"
2225 " really fast.\n"
2226 "3. Syntax highlighting shows many files in color. Not only does this look\n"
2227 " nice, it also makes it easier to spot errors and you can work faster.\n"
2228 " The other features include editing compressed files.\n"
2229 ,
2230 "Windows key mapping\n"
2231 "-------------------\n"
2232 "(this choice is only available when creating a _vimrc file)\n"
2233 "Under MS-Windows the CTRL-C key copies text to the clipboard and CTRL-V\n"
2234 "pastes text from the clipboard. There are a few more keys like these.\n"
2235 "Unfortunately, in Vim these keys normally have another meaning.\n"
2236 "1. Choose to have the keys like they normally are in Vim (useful if you\n"
2237 " also use Vim on other systems).\n"
2238 "2. Choose to have the keys work like they are used on MS-Windows (useful\n"
2239 " if you mostly work on MS-Windows).\n"
2240 ,
2241 "Mouse use\n"
2242 "---------\n"
2243 "(this choice is only available when creating a _vimrc file)\n"
2244 "The right mouse button can be used in two ways:\n"
2245 "1. The Unix way is to extend an existing selection. The popup menu is\n"
2246 " not available.\n"
2247 "2. The MS-Windows way is to show a popup menu, which allows you to\n"
2248 " copy/paste text, undo/redo, etc. Extending the selection can still be\n"
2249 " done by keeping SHIFT pressed while using the left mouse button\n"
2250 ,
2251 "Edit-with-Vim context menu entry\n"
2252 "--------------------------------\n"
2253 "(this choice is only available when gvim.exe and gvimext.dll are present)\n"
2254 "You can associate different file types with Vim, so that you can (double)\n"
2255 "click on a file to edit it with Vim. This means you have to individually\n"
2256 "select each file type.\n"
2257 "An alternative is the option offered here: Install an \"Edit with Vim\"\n"
2258 "entry in the popup menu for the right mouse button. This means you can\n"
2259 "edit any file with Vim.\n"
2260 ,
2261 "\"Open With...\" context menu entry\n"
2262 "--------------------------------\n"
2263 "(this choice is only available when gvim.exe is present)\n"
2264 "This option adds Vim to the \"Open With...\" entry in the popup menu for\n"
2265 "the right mouse button. This also makes it possible to edit HTML files\n"
2266 "directly from Internet Explorer.\n"
2267 ,
2268 "Add Vim to the Start menu\n"
2269 "-------------------------\n"
2270 "In Windows 95 and later, Vim can be added to the Start menu. This will\n"
2271 "create a submenu with an entry for vim, gvim, evim, vimdiff, etc..\n"
2272 ,
2273 "Icons on the desktop\n"
2274 "--------------------\n"
2275 "(these choices are only available when installing gvim)\n"
2276 "In Windows 95 and later, shortcuts (icons) can be created on the Desktop.\n"
2277 ,
2278 "Create plugin directories\n"
2279 "-------------------------\n"
2280 "Plugin directories allow extending Vim by dropping a file into a directory.\n"
2281 "This choice allows creating them in $HOME (if you have a home directory) or\n"
2282 "$VIM (used for everybody on the system).\n"
2283 ,
2284 NULL
2285 };
2286 int i;
2287 int c;
2288
2289 rewind(stdin);
2290 printf("\n");
2291 for (i = 0; items[i] != NULL; ++i)
2292 {
2293 printf(items[i]);
2294 printf("\n");
2295 printf("Hit Enter to continue, b (back) or q (quit help): ");
2296 c = getchar();
2297 rewind(stdin);
2298 if (c == 'b' || c == 'B')
2299 {
2300 if (i == 0)
2301 --i;
2302 else
2303 i -= 2;
2304 }
2305 if (c == 'q' || c == 'Q')
2306 break;
2307 printf("\n");
2308 }
2309 }
2310
2311 /*
2312 * Install the choices.
2313 */
2314 static void
2315 install(void)
2316 {
2317 int i;
2318
2319 /* Install the selected choices. */
2320 for (i = 0; i < choice_count; ++i)
2321 if (choices[i].installfunc != NULL && choices[i].active)
2322 (choices[i].installfunc)(i);
2323
2324 /* Add some entries to the registry, if needed. */
2325 if (install_popup
2326 || install_openwith
2327 || (need_uninstall_entry && interactive)
2328 || !interactive)
2329 install_registry();
2330
2331 #ifdef WIN3264
2332 /* Register gvim with OLE. */
2333 if (has_gvim)
2334 install_OLE_register();
2335 #endif
2336 }
2337
2338 /*
2339 * request_choice
2340 */
2341 static void
2342 request_choice(void)
2343 {
2344 int i;
2345
2346 printf("\n\nInstall will do for you:\n");
2347 for (i = 0; i < choice_count; ++i)
2348 if (choices[i].active)
2349 printf("%2d %s\n", i + 1, choices[i].text);
2350 printf("To change an item, enter its number\n\n");
2351 printf("Enter item number, h (help), d (do it) or q (quit): ");
2352 }
2353
2354 int
2355 main(int argc, char **argv)
2356 {
2357 int i;
2358 char buf[BUFSIZE];
2359
2360 /*
2361 * Run interactively if there are no command line arguments.
2362 */
2363 if (argc > 1)
2364 interactive = 0;
2365 else
2366 interactive = 1;
2367
2368 /* Initialize this program. */
2369 do_inits(argv);
2370
2371 #ifdef WIN3264
2372 if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
2373 {
2374 /* Only check for already installed Vims. Used by NSIS installer. */
2375 i = uninstall_check();
2376
2377 /* Find the value of $VIM, because NSIS isn't able to do this by
2378 * itself. */
2379 get_vim_env();
2380
2381 /* When nothing found exit quietly. If something found wait for
2382 * return pressed. */
2383 if (i)
2384 myexit(0);
2385 exit(0);
2386 }
2387 #endif
2388
2389 printf("This program sets up the installation of Vim "
2390 VIM_VERSION_MEDIUM "\n\n");
2391
2392 /* Check if the user unpacked the archives properly. */
2393 check_unpack();
2394
2395 #ifdef WIN3264
2396 /* Check for already installed Vims. */
2397 if (interactive)
2398 uninstall_check();
2399 #endif
2400
2401 /* Find out information about the system. */
2402 inspect_system();
2403
2404 if (interactive)
2405 {
2406 /* Setup all the choices. */
2407 setup_choices();
2408
2409 /* Let the user change choices and finally install (or quit). */
2410 for (;;)
2411 {
2412 request_choice();
2413 rewind(stdin);
2414 if (scanf("%99s", buf) == 1)
2415 {
2416 if (isdigit(buf[0]))
2417 {
2418 /* Change a choice. */
2419 i = atoi(buf);
2420 if (i > 0 && i <= choice_count && choices[i - 1].active)
2421 (choices[i - 1].changefunc)(i - 1);
2422 else
2423 printf("\nIllegal choice\n");
2424 }
2425 else if (buf[0] == 'h' || buf[0] == 'H')
2426 {
2427 /* Help */
2428 show_help();
2429 }
2430 else if (buf[0] == 'd' || buf[0] == 'D')
2431 {
2432 /* Install! */
2433 install();
2434 printf("\nThat finishes the installation. Happy Vimming!\n");
2435 break;
2436 }
2437 else if (buf[0] == 'q' || buf[0] == 'Q')
2438 {
2439 /* Quit */
2440 printf("\nExiting without anything done\n");
2441 break;
2442 }
2443 else
2444 printf("\nIllegal choice\n");
2445 }
2446 }
2447 printf("\n");
2448 }
2449 else
2450 {
2451 /*
2452 * Run non-interactive - setup according to the command line switches
2453 */
2454 command_line_setup_choices(argc, argv);
2455 install();
2456 }
2457
2458 myexit(0);
2459 /*NOTREACHED*/
2460 return 0;
2461 }