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