blob: e5d1f75fd391da1839ed70017c690c8e90aa1c7c [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * dosinst.c: Install program for Vim on MS-DOS and MS-Windows
12 *
13 * Compile with Make_mvc.mak, Make_bc3.mak, Make_bc5.mak or Make_djg.mak.
14 */
15
16/*
17 * Include common code for dosinst.c and uninstal.c.
18 */
19#define DOSINST
20#include "dosinst.h"
21
Bram Moolenaar6199d432017-10-14 19:05:44 +020022#define GVIMEXT64_PATH "GvimExt64\\gvimext.dll"
23#define GVIMEXT32_PATH "GvimExt32\\gvimext.dll"
24
Bram Moolenaar071d4272004-06-13 20:20:40 +000025/* Macro to do an error check I was typing over and over */
Bram Moolenaar6f470022018-04-10 18:47:20 +020026#define CHECK_REG_ERROR(code) \
27 do { \
28 if (code != ERROR_SUCCESS) \
29 { \
30 printf("%ld error number: %ld\n", (long)__LINE__, (long)code); \
31 return 1; \
32 } \
33 } while (0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000034
35int has_vim = 0; /* installable vim.exe exists */
36int has_gvim = 0; /* installable gvim.exe exists */
37
38char oldvimrc[BUFSIZE]; /* name of existing vimrc file */
39char vimrc[BUFSIZE]; /* name of vimrc file to create */
40
41char *default_bat_dir = NULL; /* when not NULL, use this as the default
42 directory to write .bat files in */
43char *default_vim_dir = NULL; /* when not NULL, use this as the default
44 install dir for NSIS */
Bram Moolenaar071d4272004-06-13 20:20:40 +000045
46/*
47 * Structure used for each choice the user can make.
48 */
49struct choice
50{
51 int active; /* non-zero when choice is active */
52 char *text; /* text displayed for this choice */
53 void (*changefunc)(int idx); /* function to change this choice */
54 int arg; /* argument for function */
55 void (*installfunc)(int idx); /* function to install this choice */
56};
57
58struct choice choices[30]; /* choices the user can make */
59int choice_count = 0; /* number of choices available */
60
61#define TABLE_SIZE(s) (int)(sizeof(s) / sizeof(*s))
62
63enum
64{
65 compat_vi = 1,
66 compat_some_enhancements,
67 compat_all_enhancements
68};
69char *(compat_choices[]) =
70{
71 "\nChoose the default way to run Vim:",
72 "Vi compatible",
Bram Moolenaarfff2bee2010-05-15 13:56:02 +020073 "with some Vim enhancements",
Bram Moolenaar071d4272004-06-13 20:20:40 +000074 "with syntax highlighting and other features switched on",
75};
76int compat_choice = (int)compat_all_enhancements;
77char *compat_text = "- run Vim %s";
78
79enum
80{
81 remap_no = 1,
82 remap_win
83};
84char *(remap_choices[]) =
85{
86 "\nChoose:",
87 "Do not remap keys for Windows behavior",
Bram Moolenaar6199d432017-10-14 19:05:44 +020088 "Remap a few keys for Windows behavior (CTRL-V, CTRL-C, CTRL-F, etc)",
Bram Moolenaar071d4272004-06-13 20:20:40 +000089};
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +020090int remap_choice = (int)remap_no;
Bram Moolenaar071d4272004-06-13 20:20:40 +000091char *remap_text = "- %s";
92
93enum
94{
95 mouse_xterm = 1,
Bram Moolenaarb9fce6c2017-10-28 18:50:01 +020096 mouse_mswin,
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +020097 mouse_default
Bram Moolenaar071d4272004-06-13 20:20:40 +000098};
99char *(mouse_choices[]) =
100{
101 "\nChoose the way how Vim uses the mouse:",
102 "right button extends selection (the Unix way)",
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +0200103 "right button has a popup menu, left button starts select mode (the Windows way)",
104 "right button has a popup menu, left button starts visual mode",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105};
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +0200106int mouse_choice = (int)mouse_default;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000107char *mouse_text = "- The mouse %s";
108
109enum
110{
111 vimfiles_dir_none = 1,
112 vimfiles_dir_vim,
113 vimfiles_dir_home
114};
115static char *(vimfiles_dir_choices[]) =
116{
117 "\nCreate plugin directories:",
118 "No",
119 "In the VIM directory",
120 "In your HOME directory",
121};
122static int vimfiles_dir_choice;
123
124/* non-zero when selected to install the popup menu entry. */
125static int install_popup = 0;
126
127/* non-zero when selected to install the "Open with" entry. */
128static int install_openwith = 0;
129
130/* non-zero when need to add an uninstall entry in the registry */
131static int need_uninstall_entry = 0;
132
133/*
134 * Definitions of the directory name (under $VIM) of the vimfiles directory
135 * and its subdirectories:
136 */
137static char *(vimfiles_subdirs[]) =
138{
139 "colors",
140 "compiler",
141 "doc",
142 "ftdetect",
143 "ftplugin",
144 "indent",
145 "keymap",
146 "plugin",
147 "syntax",
148};
149
150/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151 * Obtain a choice from a table.
152 * First entry is a question, others are choices.
153 */
154 static int
155get_choice(char **table, int entries)
156{
157 int answer;
158 int idx;
159 char dummy[100];
160
161 do
162 {
163 for (idx = 0; idx < entries; ++idx)
164 {
165 if (idx)
166 printf("%2d ", idx);
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +0200167 puts(table[idx]);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000168 }
169 printf("Choice: ");
170 if (scanf("%d", &answer) != 1)
171 {
172 scanf("%99s", dummy);
173 answer = 0;
174 }
175 }
176 while (answer < 1 || answer >= entries);
177
178 return answer;
179}
180
181/*
182 * Check if the user unpacked the archives properly.
183 * Sets "runtimeidx".
184 */
185 static void
186check_unpack(void)
187{
188 char buf[BUFSIZE];
189 FILE *fd;
190 struct stat st;
191
192 /* check for presence of the correct version number in installdir[] */
193 runtimeidx = strlen(installdir) - strlen(VIM_VERSION_NODOT);
194 if (runtimeidx <= 0
195 || stricmp(installdir + runtimeidx, VIM_VERSION_NODOT) != 0
196 || (installdir[runtimeidx - 1] != '/'
197 && installdir[runtimeidx - 1] != '\\'))
198 {
199 printf("ERROR: Install program not in directory \"%s\"\n",
200 VIM_VERSION_NODOT);
201 printf("This program can only work when it is located in its original directory\n");
202 myexit(1);
203 }
204
205 /* check if filetype.vim is present, which means the runtime archive has
206 * been unpacked */
207 sprintf(buf, "%s\\filetype.vim", installdir);
208 if (stat(buf, &st) < 0)
209 {
210 printf("ERROR: Cannot find filetype.vim in \"%s\"\n", installdir);
211 printf("It looks like you did not unpack the runtime archive.\n");
212 printf("You must unpack the runtime archive \"vim%srt.zip\" before installing.\n",
213 VIM_VERSION_NODOT + 3);
214 myexit(1);
215 }
216
217 /* Check if vim.exe or gvim.exe is in the current directory. */
218 if ((fd = fopen("gvim.exe", "r")) != NULL)
219 {
220 fclose(fd);
221 has_gvim = 1;
222 }
223 if ((fd = fopen("vim.exe", "r")) != NULL)
224 {
225 fclose(fd);
226 has_vim = 1;
227 }
228 if (!has_gvim && !has_vim)
229 {
230 printf("ERROR: Cannot find any Vim executables in \"%s\"\n\n",
231 installdir);
232 myexit(1);
233 }
234}
235
236/*
237 * Compare paths "p[plen]" to "q[qlen]". Return 0 if they match.
238 * Ignores case and differences between '/' and '\'.
239 * "plen" and "qlen" can be negative, strlen() is used then.
240 */
241 static int
242pathcmp(char *p, int plen, char *q, int qlen)
243{
244 int i;
245
246 if (plen < 0)
247 plen = strlen(p);
248 if (qlen < 0)
249 qlen = strlen(q);
250 for (i = 0; ; ++i)
251 {
252 /* End of "p": check if "q" also ends or just has a slash. */
253 if (i == plen)
254 {
255 if (i == qlen) /* match */
256 return 0;
257 if (i == qlen - 1 && (q[i] == '\\' || q[i] == '/'))
258 return 0; /* match with trailing slash */
259 return 1; /* no match */
260 }
261
262 /* End of "q": check if "p" also ends or just has a slash. */
263 if (i == qlen)
264 {
265 if (i == plen) /* match */
266 return 0;
267 if (i == plen - 1 && (p[i] == '\\' || p[i] == '/'))
268 return 0; /* match with trailing slash */
269 return 1; /* no match */
270 }
271
272 if (!(mytoupper(p[i]) == mytoupper(q[i])
273 || ((p[i] == '/' || p[i] == '\\')
274 && (q[i] == '/' || q[i] == '\\'))))
275 return 1; /* no match */
276 }
277 /*NOTREACHED*/
278}
279
280/*
281 * If the executable "**destination" is in the install directory, find another
282 * one in $PATH.
283 * On input "**destination" is the path of an executable in allocated memory
284 * (or NULL).
285 * "*destination" is set to NULL or the location of the file.
286 */
287 static void
288findoldfile(char **destination)
289{
290 char *bp = *destination;
291 size_t indir_l = strlen(installdir);
292 char *cp = bp + indir_l;
293 char *tmpname;
294 char *farname;
295
296 /*
297 * No action needed if exe not found or not in this directory.
298 */
299 if (bp == NULL
300 || strnicmp(bp, installdir, indir_l) != 0
301 || strchr("/\\", *cp++) == NULL
302 || strchr(cp, '\\') != NULL
303 || strchr(cp, '/') != NULL)
304 return;
305
306 tmpname = alloc((int)strlen(cp) + 1);
307 strcpy(tmpname, cp);
308 tmpname[strlen(tmpname) - 1] = 'x'; /* .exe -> .exx */
309
310 if (access(tmpname, 0) == 0)
311 {
312 printf("\nERROR: %s and %s clash. Remove or rename %s.\n",
313 tmpname, cp, tmpname);
314 myexit(1);
315 }
316
317 if (rename(cp, tmpname) != 0)
318 {
319 printf("\nERROR: failed to rename %s to %s: %s\n",
320 cp, tmpname, strerror(0));
321 myexit(1);
322 }
323
324 farname = searchpath_save(cp);
325
326 if (rename(tmpname, cp) != 0)
327 {
328 printf("\nERROR: failed to rename %s back to %s: %s\n",
329 tmpname, cp, strerror(0));
330 myexit(1);
331 }
332
333 free(*destination);
334 free(tmpname);
335 *destination = farname;
336}
337
338/*
339 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
340 * When "check_bat_only" is TRUE, only find "default_bat_dir".
341 */
342 static void
343find_bat_exe(int check_bat_only)
344{
345 int i;
346
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000347 /* avoid looking in the "installdir" by chdir to system root */
348 mch_chdir(sysdrive);
349 mch_chdir("\\");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000350
351 for (i = 1; i < TARGET_COUNT; ++i)
352 {
353 targets[i].oldbat = searchpath_save(targets[i].batname);
354 if (!check_bat_only)
355 targets[i].oldexe = searchpath_save(targets[i].exename);
356
357 if (default_bat_dir == NULL && targets[i].oldbat != NULL)
358 {
359 default_bat_dir = alloc(strlen(targets[i].oldbat) + 1);
360 strcpy(default_bat_dir, targets[i].oldbat);
361 remove_tail(default_bat_dir);
362 }
363 if (check_bat_only && targets[i].oldbat != NULL)
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000364 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000365 free(targets[i].oldbat);
Bram Moolenaar42bbef42006-03-25 22:02:07 +0000366 targets[i].oldbat = NULL;
367 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368 }
369
370 mch_chdir(installdir);
371}
372
Bram Moolenaar071d4272004-06-13 20:20:40 +0000373/*
374 * Get the value of $VIMRUNTIME or $VIM and write it in $TEMP/vimini.ini, so
375 * that NSIS can read it.
376 * When not set, use the directory of a previously installed Vim.
377 */
378 static void
379get_vim_env(void)
380{
381 char *vim;
382 char buf[BUFSIZE];
383 FILE *fd;
384 char fname[BUFSIZE];
385
386 /* First get $VIMRUNTIME. If it's set, remove the tail. */
387 vim = getenv("VIMRUNTIME");
Bram Moolenaar181ace22013-02-13 14:36:44 +0100388 if (vim != NULL && *vim != 0 && strlen(vim) < BUFSIZE)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389 {
390 strcpy(buf, vim);
391 remove_tail(buf);
392 vim = buf;
393 }
394 else
395 {
396 vim = getenv("VIM");
397 if (vim == NULL || *vim == 0)
398 {
399 /* Use the directory from an old uninstall entry. */
400 if (default_vim_dir != NULL)
401 vim = default_vim_dir;
402 else
403 /* Let NSIS know there is no default, it should use
Bram Moolenaarb8017e72007-05-10 18:59:07 +0000404 * $PROGRAMFILES. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405 vim = "";
406 }
407 }
408
409 /* NSIS also uses GetTempPath(), thus we should get the same directory
410 * name as where NSIS will look for vimini.ini. */
411 GetTempPath(BUFSIZE, fname);
412 add_pathsep(fname);
413 strcat(fname, "vimini.ini");
414
415 fd = fopen(fname, "w");
416 if (fd != NULL)
417 {
418 /* Make it look like an .ini file, so that NSIS can read it with a
419 * ReadINIStr command. */
420 fprintf(fd, "[vimini]\n");
421 fprintf(fd, "dir=\"%s\"\n", vim);
422 fclose(fd);
423 }
424 else
425 {
426 printf("Failed to open %s\n", fname);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200427 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000428 }
429}
430
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200431static int num_windows;
432
433/*
434 * Callback used for EnumWindows():
435 * Count the window if the title looks like it is for the uninstaller.
436 */
437/*ARGSUSED*/
438 static BOOL CALLBACK
439window_cb(HWND hwnd, LPARAM lparam)
440{
441 char title[256];
442
443 title[0] = 0;
444 GetWindowText(hwnd, title, 256);
445 if (strstr(title, "Vim ") != NULL && strstr(title, "Uninstall:") != NULL)
446 ++num_windows;
447 return TRUE;
448}
449
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450/*
451 * Check for already installed Vims.
452 * Return non-zero when found one.
453 */
454 static int
Bram Moolenaar442b4222010-05-24 21:34:22 +0200455uninstall_check(int skip_question)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000456{
457 HKEY key_handle;
458 HKEY uninstall_key_handle;
459 char *uninstall_key = "software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
460 char subkey_name_buff[BUFSIZE];
461 char temp_string_buffer[BUFSIZE];
462 DWORD local_bufsize = BUFSIZE;
463 FILETIME temp_pfiletime;
464 DWORD key_index;
465 char input;
466 long code;
467 DWORD value_type;
468 DWORD orig_num_keys;
469 DWORD new_num_keys;
470 int foundone = 0;
471
Bram Moolenaar760d14a2010-07-31 22:03:44 +0200472 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0,
473 KEY_WOW64_64KEY | KEY_READ, &key_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000474 CHECK_REG_ERROR(code);
475
476 for (key_index = 0;
477 RegEnumKeyEx(key_handle, key_index, subkey_name_buff, &local_bufsize,
478 NULL, NULL, NULL, &temp_pfiletime) != ERROR_NO_MORE_ITEMS;
479 key_index++)
480 {
481 local_bufsize = BUFSIZE;
482 if (strncmp("Vim", subkey_name_buff, 3) == 0)
483 {
484 /* Open the key named Vim* */
Bram Moolenaar760d14a2010-07-31 22:03:44 +0200485 code = RegOpenKeyEx(key_handle, subkey_name_buff, 0,
486 KEY_WOW64_64KEY | KEY_READ, &uninstall_key_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487 CHECK_REG_ERROR(code);
488
489 /* get the DisplayName out of it to show the user */
490 code = RegQueryValueEx(uninstall_key_handle, "displayname", 0,
491 &value_type, (LPBYTE)temp_string_buffer,
492 &local_bufsize);
493 local_bufsize = BUFSIZE;
494 CHECK_REG_ERROR(code);
495
496 foundone = 1;
497 printf("\n*********************************************************\n");
498 printf("Vim Install found what looks like an existing Vim version.\n");
499 printf("The name of the entry is:\n");
500 printf("\n \"%s\"\n\n", temp_string_buffer);
501
502 printf("Installing the new version will disable part of the existing version.\n");
503 printf("(The batch files used in a console and the \"Edit with Vim\" entry in\n");
504 printf("the popup menu will use the new version)\n");
505
Bram Moolenaar442b4222010-05-24 21:34:22 +0200506 if (skip_question)
507 printf("\nRunning uninstall program for \"%s\"\n", temp_string_buffer);
508 else
509 printf("\nDo you want to uninstall \"%s\" now?\n(y)es/(n)o) ", temp_string_buffer);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000510 fflush(stdout);
511
512 /* get the UninstallString */
513 code = RegQueryValueEx(uninstall_key_handle, "uninstallstring", 0,
514 &value_type, (LPBYTE)temp_string_buffer, &local_bufsize);
515 local_bufsize = BUFSIZE;
516 CHECK_REG_ERROR(code);
517
518 /* Remember the directory, it is used as the default for NSIS. */
519 default_vim_dir = alloc(strlen(temp_string_buffer) + 1);
520 strcpy(default_vim_dir, temp_string_buffer);
521 remove_tail(default_vim_dir);
522 remove_tail(default_vim_dir);
523
524 input = 'n';
525 do
526 {
527 if (input != 'n')
528 printf("%c is an invalid reply. Please enter either 'y' or 'n'\n", input);
529
Bram Moolenaar442b4222010-05-24 21:34:22 +0200530 if (skip_question)
531 input = 'y';
532 else
533 {
534 rewind(stdin);
535 scanf("%c", &input);
536 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537 switch (input)
538 {
539 case 'y':
540 case 'Y':
541 /* save the number of uninstall keys so we can know if
542 * it changed */
543 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
544 &orig_num_keys, NULL, NULL, NULL,
545 NULL, NULL, NULL, NULL);
546
Bram Moolenaar442b4222010-05-24 21:34:22 +0200547 /* Find existing .bat files before deleting them. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000548 find_bat_exe(TRUE);
549
550 /* Execute the uninstall program. Put it in double
551 * quotes if there is an embedded space. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000552 {
553 char buf[BUFSIZE];
554
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200555 if (strchr(temp_string_buffer, ' ') != NULL)
556 sprintf(buf, "\"%s\"", temp_string_buffer);
557 else
558 strcpy(buf, temp_string_buffer);
559 run_command(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000560 }
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200561
562 /* Count the number of windows with a title that match
563 * the installer, so that we can check when it's done.
564 * The uninstaller copies itself, executes the copy
565 * and exits, thus we can't wait for the process to
566 * finish. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200567 sleep(1); /* wait for uninstaller to start up */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200568 num_windows = 0;
569 EnumWindows(window_cb, 0);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200570 sleep(1); /* wait for windows to be counted */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200571 if (num_windows == 0)
572 {
573 /* Did not find the uninstaller, ask user to press
574 * Enter when done. Just in case. */
575 printf("Press Enter when the uninstaller is finished\n");
576 rewind(stdin);
577 (void)getchar();
578 }
579 else
580 {
581 printf("Waiting for the uninstaller to finish (press CTRL-C to abort).");
582 do
583 {
584 printf(".");
585 fflush(stdout);
586 num_windows = 0;
587 EnumWindows(window_cb, 0);
Bram Moolenaarab8205e2010-07-07 15:14:03 +0200588 sleep(1); /* wait for windows to be counted */
Bram Moolenaarb230bd52010-05-25 21:02:00 +0200589 } while (num_windows > 0);
590 }
591 printf("\nDone!\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000592
Bram Moolenaarfff2bee2010-05-15 13:56:02 +0200593 /* Check if an uninstall reg key was deleted.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000594 * if it was, we want to decrement key_index.
595 * if we don't do this, we will skip the key
596 * immediately after any key that we delete. */
597 RegQueryInfoKey(key_handle, NULL, NULL, NULL,
598 &new_num_keys, NULL, NULL, NULL,
599 NULL, NULL, NULL, NULL);
600 if (new_num_keys < orig_num_keys)
601 key_index--;
602
603 input = 'y';
604 break;
605
606 case 'n':
607 case 'N':
608 /* Do not uninstall */
609 input = 'n';
610 break;
611
612 default: /* just drop through and redo the loop */
613 break;
614 }
615
616 } while (input != 'n' && input != 'y');
617
618 RegCloseKey(uninstall_key_handle);
619 }
620 }
621 RegCloseKey(key_handle);
622
623 return foundone;
624}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000625
626/*
627 * Find out information about the system.
628 */
629 static void
630inspect_system(void)
631{
632 char *p;
633 char buf[BUFSIZE];
634 FILE *fd;
635 int i;
636 int foundone;
637
638 /* This may take a little while, let the user know what we're doing. */
639 printf("Inspecting system...\n");
640
641 /*
642 * If $VIM is set, check that it's pointing to our directory.
643 */
644 p = getenv("VIM");
645 if (p != NULL && pathcmp(p, -1, installdir, runtimeidx - 1) != 0)
646 {
647 printf("------------------------------------------------------\n");
648 printf("$VIM is set to \"%s\".\n", p);
649 printf("This is different from where this version of Vim is:\n");
650 strcpy(buf, installdir);
651 *(buf + runtimeidx - 1) = NUL;
652 printf("\"%s\"\n", buf);
653 printf("You must adjust or remove the setting of $VIM,\n");
654 if (interactive)
655 {
656 printf("to be able to use this install program.\n");
657 myexit(1);
658 }
659 printf("otherwise Vim WILL NOT WORK properly!\n");
660 printf("------------------------------------------------------\n");
661 }
662
663 /*
664 * If $VIMRUNTIME is set, check that it's pointing to our runtime directory.
665 */
666 p = getenv("VIMRUNTIME");
667 if (p != NULL && pathcmp(p, -1, installdir, -1) != 0)
668 {
669 printf("------------------------------------------------------\n");
670 printf("$VIMRUNTIME is set to \"%s\".\n", p);
671 printf("This is different from where this version of Vim is:\n");
672 printf("\"%s\"\n", installdir);
673 printf("You must adjust or remove the setting of $VIMRUNTIME,\n");
674 if (interactive)
675 {
676 printf("to be able to use this install program.\n");
677 myexit(1);
678 }
679 printf("otherwise Vim WILL NOT WORK properly!\n");
680 printf("------------------------------------------------------\n");
681 }
682
683 /*
684 * Check if there is a vim.[exe|bat|, gvim.[exe|bat|, etc. in the path.
685 */
686 find_bat_exe(FALSE);
687
688 /*
689 * A .exe in the install directory may be found anyway on Windows 2000.
690 * Check for this situation and find another executable if necessary.
691 * w.briscoe@ponl.com 2001-01-20
692 */
693 foundone = 0;
694 for (i = 1; i < TARGET_COUNT; ++i)
695 {
696 findoldfile(&(targets[i].oldexe));
697 if (targets[i].oldexe != NULL)
698 foundone = 1;
699 }
700
701 if (foundone)
702 {
703 printf("Warning: Found Vim executable(s) in your $PATH:\n");
704 for (i = 1; i < TARGET_COUNT; ++i)
705 if (targets[i].oldexe != NULL)
706 printf("%s\n", targets[i].oldexe);
707 printf("It will be used instead of the version you are installing.\n");
708 printf("Please delete or rename it, or adjust your $PATH setting.\n");
709 }
710
711 /*
712 * Check if there is an existing ../_vimrc or ../.vimrc file.
713 */
714 strcpy(oldvimrc, installdir);
715 strcpy(oldvimrc + runtimeidx, "_vimrc");
716 if ((fd = fopen(oldvimrc, "r")) == NULL)
717 {
718 strcpy(oldvimrc + runtimeidx, "vimrc~1"); /* short version of .vimrc */
719 if ((fd = fopen(oldvimrc, "r")) == NULL)
720 {
721 strcpy(oldvimrc + runtimeidx, ".vimrc");
722 fd = fopen(oldvimrc, "r");
723 }
724 }
725 if (fd != NULL)
726 fclose(fd);
727 else
728 *oldvimrc = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729}
730
731/*
732 * Add a dummy choice to avoid that the numbering changes depending on items
733 * in the environment. The user may type a number he remembered without
734 * looking.
735 */
736 static void
737add_dummy_choice(void)
738{
739 choices[choice_count].installfunc = NULL;
740 choices[choice_count].active = 0;
741 choices[choice_count].changefunc = NULL;
742 choices[choice_count].installfunc = NULL;
743 ++choice_count;
744}
745
746/***********************************************
747 * stuff for creating the batch files.
748 */
749
750/*
751 * Install the vim.bat, gvim.bat, etc. files.
752 */
753 static void
754install_bat_choice(int idx)
755{
756 char *batpath = targets[choices[idx].arg].batpath;
757 char *oldname = targets[choices[idx].arg].oldbat;
758 char *exename = targets[choices[idx].arg].exenamearg;
759 char *vimarg = targets[choices[idx].arg].exearg;
760 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761
762 if (*batpath != NUL)
763 {
764 fd = fopen(batpath, "w");
765 if (fd == NULL)
766 printf("\nERROR: Cannot open \"%s\" for writing.\n", batpath);
767 else
768 {
769 need_uninstall_entry = 1;
770
771 fprintf(fd, "@echo off\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000772 fprintf(fd, "rem -- Run Vim --\n");
773 fprintf(fd, "\n");
Bram Moolenaare609ad52016-03-28 23:05:48 +0200774 fprintf(fd, "setlocal\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000776 /* Don't use double quotes for the "set" argument, also when it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000777 * contains a space. The quotes would be included in the value
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000778 * for MSDOS and NT.
779 * The order of preference is:
780 * 1. $VIMRUNTIME/vim.exe (user preference)
781 * 2. $VIM/vim70/vim.exe (hard coded version)
782 * 3. installdir/vim.exe (hard coded install directory)
783 */
784 fprintf(fd, "set VIM_EXE_DIR=%s\n", installdir);
785 fprintf(fd, "if exist \"%%VIM%%\\%s\\%s\" set VIM_EXE_DIR=%%VIM%%\\%s\n",
786 VIM_VERSION_NODOT, exename, VIM_VERSION_NODOT);
787 fprintf(fd, "if exist \"%%VIMRUNTIME%%\\%s\" set VIM_EXE_DIR=%%VIMRUNTIME%%\n", exename);
788 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789
790 /* Give an error message when the executable could not be found. */
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000791 fprintf(fd, "if exist \"%%VIM_EXE_DIR%%\\%s\" goto havevim\n",
792 exename);
793 fprintf(fd, "echo \"%%VIM_EXE_DIR%%\\%s\" not found\n", exename);
794 fprintf(fd, "goto eof\n");
795 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796 fprintf(fd, ":havevim\n");
797
798 fprintf(fd, "rem collect the arguments in VIMARGS for Win95\n");
799 fprintf(fd, "set VIMARGS=\n");
800 if (*exename == 'g')
801 fprintf(fd, "set VIMNOFORK=\n");
802 fprintf(fd, ":loopstart\n");
803 fprintf(fd, "if .%%1==. goto loopend\n");
804 if (*exename == 'g')
805 {
Bram Moolenaare609ad52016-03-28 23:05:48 +0200806 fprintf(fd, "if NOT .%%1==.--nofork goto noforklongarg\n");
807 fprintf(fd, "set VIMNOFORK=1\n");
808 fprintf(fd, ":noforklongarg\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n");
810 fprintf(fd, "set VIMNOFORK=1\n");
811 fprintf(fd, ":noforkarg\n");
812 }
813 fprintf(fd, "set VIMARGS=%%VIMARGS%% %%1\n");
814 fprintf(fd, "shift\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000815 fprintf(fd, "goto loopstart\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 fprintf(fd, ":loopend\n");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000817 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000819 fprintf(fd, "if .%%OS%%==.Windows_NT goto ntaction\n");
820 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000821
822 /* For gvim.exe use "start" to avoid that the console window stays
823 * open. */
824 if (*exename == 'g')
825 {
826 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto nofork\n");
827 fprintf(fd, "start ");
828 }
829
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000830 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
831 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
832 exename, vimarg);
833 fprintf(fd, "goto eof\n");
834 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835
836 if (*exename == 'g')
837 {
838 fprintf(fd, ":nofork\n");
839 fprintf(fd, "start /w ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000840 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
841 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%VIMARGS%%\n",
842 exename, vimarg);
843 fprintf(fd, "goto eof\n");
844 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 }
846
847 fprintf(fd, ":ntaction\n");
848 fprintf(fd, "rem for WinNT we can use %%*\n");
849
850 /* For gvim.exe use "start /b" to avoid that the console window
851 * stays open. */
852 if (*exename == 'g')
853 {
854 fprintf(fd, "if .%%VIMNOFORK%%==.1 goto noforknt\n");
855 fprintf(fd, "start \"dummy\" /b ");
856 }
857
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000858 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
859 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n", exename, vimarg);
860 fprintf(fd, "goto eof\n");
861 fprintf(fd, "\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862
863 if (*exename == 'g')
864 {
865 fprintf(fd, ":noforknt\n");
866 fprintf(fd, "start \"dummy\" /b /wait ");
Bram Moolenaar97b2ad32006-03-18 21:40:56 +0000867 /* Always use quotes, $VIM or $VIMRUNTIME might have a space. */
868 fprintf(fd, "\"%%VIM_EXE_DIR%%\\%s\" %s %%*\n",
869 exename, vimarg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000870 }
871
872 fprintf(fd, "\n:eof\n");
873 fprintf(fd, "set VIMARGS=\n");
874 if (*exename == 'g')
875 fprintf(fd, "set VIMNOFORK=\n");
876
877 fclose(fd);
878 printf("%s has been %s\n", batpath,
879 oldname == NULL ? "created" : "overwritten");
880 }
881 }
882}
883
884/*
885 * Make the text string for choice "idx".
886 * The format "fmt" is must have one %s item, which "arg" is used for.
887 */
888 static void
889alloc_text(int idx, char *fmt, char *arg)
890{
891 if (choices[idx].text != NULL)
892 free(choices[idx].text);
893
894 choices[idx].text = alloc((int)(strlen(fmt) + strlen(arg)) - 1);
895 sprintf(choices[idx].text, fmt, arg);
896}
897
898/*
899 * Toggle the "Overwrite .../vim.bat" to "Don't overwrite".
900 */
901 static void
902toggle_bat_choice(int idx)
903{
904 char *batname = targets[choices[idx].arg].batpath;
905 char *oldname = targets[choices[idx].arg].oldbat;
906
907 if (*batname == NUL)
908 {
909 alloc_text(idx, " Overwrite %s", oldname);
910 strcpy(batname, oldname);
911 }
912 else
913 {
914 alloc_text(idx, " Do NOT overwrite %s", oldname);
915 *batname = NUL;
916 }
917}
918
919/*
920 * Do some work for a batch file entry: Append the batch file name to the path
921 * and set the text for the choice.
922 */
923 static void
924set_bat_text(int idx, char *batpath, char *name)
925{
926 strcat(batpath, name);
927
928 alloc_text(idx, " Create %s", batpath);
929}
930
931/*
932 * Select a directory to write the batch file line.
933 */
934 static void
935change_bat_choice(int idx)
936{
937 char *path;
938 char *batpath;
939 char *name;
940 int n;
941 char *s;
942 char *p;
943 int count;
944 char **names = NULL;
945 int i;
946 int target = choices[idx].arg;
947
948 name = targets[target].batname;
949 batpath = targets[target].batpath;
950
951 path = getenv("PATH");
952 if (path == NULL)
953 {
954 printf("\nERROR: The variable $PATH is not set\n");
955 return;
956 }
957
958 /*
959 * first round: count number of names in path;
960 * second round: save names to names[].
961 */
962 for (;;)
963 {
964 count = 1;
965 for (p = path; *p; )
966 {
967 s = strchr(p, ';');
968 if (s == NULL)
969 s = p + strlen(p);
970 if (names != NULL)
971 {
972 names[count] = alloc((int)(s - p) + 1);
973 strncpy(names[count], p, s - p);
974 names[count][s - p] = NUL;
975 }
976 ++count;
977 p = s;
978 if (*p != NUL)
979 ++p;
980 }
981 if (names != NULL)
982 break;
983 names = alloc((int)(count + 1) * sizeof(char *));
984 }
985 names[0] = alloc(50);
986 sprintf(names[0], "Select directory to create %s in:", name);
987 names[count] = alloc(50);
988 if (choices[idx].arg == 0)
989 sprintf(names[count], "Do not create any .bat file.");
990 else
991 sprintf(names[count], "Do not create a %s file.", name);
992 n = get_choice(names, count + 1);
993
994 if (n == count)
995 {
996 /* Selected last item, don't create bat file. */
997 *batpath = NUL;
998 if (choices[idx].arg != 0)
999 alloc_text(idx, " Do NOT create %s", name);
1000 }
1001 else
1002 {
1003 /* Selected one of the paths. For the first item only keep the path,
1004 * for the others append the batch file name. */
1005 strcpy(batpath, names[n]);
1006 add_pathsep(batpath);
1007 if (choices[idx].arg != 0)
1008 set_bat_text(idx, batpath, name);
1009 }
1010
1011 for (i = 0; i <= count; ++i)
1012 free(names[i]);
1013 free(names);
1014}
1015
1016char *bat_text_yes = "Install .bat files to use Vim at the command line:";
1017char *bat_text_no = "do NOT install .bat files to use Vim at the command line";
1018
1019 static void
1020change_main_bat_choice(int idx)
1021{
1022 int i;
1023
1024 /* let the user select a default directory or NONE */
1025 change_bat_choice(idx);
1026
1027 if (targets[0].batpath[0] != NUL)
1028 choices[idx].text = bat_text_yes;
1029 else
1030 choices[idx].text = bat_text_no;
1031
1032 /* update the individual batch file selections */
1033 for (i = 1; i < TARGET_COUNT; ++i)
1034 {
1035 /* Only make it active when the first item has a path and the vim.exe
1036 * or gvim.exe exists (there is a changefunc then). */
1037 if (targets[0].batpath[0] != NUL
1038 && choices[idx + i].changefunc != NULL)
1039 {
1040 choices[idx + i].active = 1;
1041 if (choices[idx + i].changefunc == change_bat_choice
1042 && targets[i].batpath[0] != NUL)
1043 {
1044 strcpy(targets[i].batpath, targets[0].batpath);
1045 set_bat_text(idx + i, targets[i].batpath, targets[i].batname);
1046 }
1047 }
1048 else
1049 choices[idx + i].active = 0;
1050 }
1051}
1052
1053/*
1054 * Initialize a choice for creating a batch file.
1055 */
1056 static void
1057init_bat_choice(int target)
1058{
1059 char *batpath = targets[target].batpath;
1060 char *oldbat = targets[target].oldbat;
1061 char *p;
1062 int i;
1063
1064 choices[choice_count].arg = target;
1065 choices[choice_count].installfunc = install_bat_choice;
1066 choices[choice_count].active = 1;
1067 choices[choice_count].text = NULL; /* will be set below */
1068 if (oldbat != NULL)
1069 {
1070 /* A [g]vim.bat exists: Only choice is to overwrite it or not. */
1071 choices[choice_count].changefunc = toggle_bat_choice;
1072 *batpath = NUL;
1073 toggle_bat_choice(choice_count);
1074 }
1075 else
1076 {
1077 if (default_bat_dir != NULL)
1078 /* Prefer using the same path as an existing .bat file. */
1079 strcpy(batpath, default_bat_dir);
1080 else
1081 {
1082 /* No [g]vim.bat exists: Write it to a directory in $PATH. Use
1083 * $WINDIR by default, if it's empty the first item in $PATH. */
1084 p = getenv("WINDIR");
1085 if (p != NULL && *p != NUL)
1086 strcpy(batpath, p);
1087 else
1088 {
1089 p = getenv("PATH");
1090 if (p == NULL || *p == NUL) /* "cannot happen" */
1091 strcpy(batpath, "C:/Windows");
1092 else
1093 {
1094 i = 0;
1095 while (*p != NUL && *p != ';')
1096 batpath[i++] = *p++;
1097 batpath[i] = NUL;
1098 }
1099 }
1100 }
1101 add_pathsep(batpath);
1102 set_bat_text(choice_count, batpath, targets[target].batname);
1103
1104 choices[choice_count].changefunc = change_bat_choice;
1105 }
1106 ++choice_count;
1107}
1108
1109/*
1110 * Set up the choices for installing .bat files.
1111 * For these items "arg" is the index in targets[].
1112 */
1113 static void
1114init_bat_choices(void)
1115{
1116 int i;
1117
1118 /* The first item is used to switch installing batch files on/off and
1119 * setting the default path. */
1120 choices[choice_count].text = bat_text_yes;
1121 choices[choice_count].changefunc = change_main_bat_choice;
1122 choices[choice_count].installfunc = NULL;
1123 choices[choice_count].active = 1;
1124 choices[choice_count].arg = 0;
1125 ++choice_count;
1126
1127 /* Add items for each batch file target. Only used when not disabled by
1128 * the first item. When a .exe exists, don't offer to create a .bat. */
1129 for (i = 1; i < TARGET_COUNT; ++i)
1130 if (targets[i].oldexe == NULL
1131 && (targets[i].exenamearg[0] == 'g' ? has_gvim : has_vim))
1132 init_bat_choice(i);
1133 else
1134 add_dummy_choice();
1135}
1136
1137/*
1138 * Install the vimrc file.
1139 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001140 static void
1141install_vimrc(int idx)
1142{
1143 FILE *fd, *tfd;
1144 char *fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001145
1146 /* If an old vimrc file exists, overwrite it.
1147 * Otherwise create a new one. */
1148 if (*oldvimrc != NUL)
1149 fname = oldvimrc;
1150 else
1151 fname = vimrc;
1152
1153 fd = fopen(fname, "w");
1154 if (fd == NULL)
1155 {
1156 printf("\nERROR: Cannot open \"%s\" for writing.\n", fname);
1157 return;
1158 }
1159 switch (compat_choice)
1160 {
1161 case compat_vi:
1162 fprintf(fd, "set compatible\n");
1163 break;
1164 case compat_some_enhancements:
Bram Moolenaarc73e4472016-07-29 18:33:38 +02001165 fprintf(fd, "source $VIMRUNTIME/defaults.vim\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166 break;
1167 case compat_all_enhancements:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168 fprintf(fd, "source $VIMRUNTIME/vimrc_example.vim\n");
1169 break;
1170 }
1171 switch (remap_choice)
1172 {
1173 case remap_no:
1174 break;
1175 case remap_win:
1176 fprintf(fd, "source $VIMRUNTIME/mswin.vim\n");
1177 break;
1178 }
1179 switch (mouse_choice)
1180 {
1181 case mouse_xterm:
1182 fprintf(fd, "behave xterm\n");
1183 break;
1184 case mouse_mswin:
1185 fprintf(fd, "behave mswin\n");
1186 break;
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02001187 case mouse_default:
1188 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189 }
1190 if ((tfd = fopen("diff.exe", "r")) != NULL)
1191 {
1192 /* Use the diff.exe that comes with the self-extracting gvim.exe. */
1193 fclose(tfd);
1194 fprintf(fd, "\n");
1195 fprintf(fd, "set diffexpr=MyDiff()\n");
1196 fprintf(fd, "function MyDiff()\n");
1197 fprintf(fd, " let opt = '-a --binary '\n");
1198 fprintf(fd, " if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif\n");
1199 fprintf(fd, " if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif\n");
Bram Moolenaar12365ce2018-05-13 14:45:25 +02001200 /* Use quotes only when needed, they may cause trouble.
1201 * Always escape "!". */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202 fprintf(fd, " let arg1 = v:fname_in\n");
1203 fprintf(fd, " if arg1 =~ ' ' | let arg1 = '\"' . arg1 . '\"' | endif\n");
Bram Moolenaar12365ce2018-05-13 14:45:25 +02001204 fprintf(fd, " let arg1 = substitute(arg1, '!', '\\!', 'g')\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205 fprintf(fd, " let arg2 = v:fname_new\n");
1206 fprintf(fd, " if arg2 =~ ' ' | let arg2 = '\"' . arg2 . '\"' | endif\n");
Bram Moolenaar12365ce2018-05-13 14:45:25 +02001207 fprintf(fd, " let arg2 = substitute(arg2, '!', '\\!', 'g')\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208 fprintf(fd, " let arg3 = v:fname_out\n");
1209 fprintf(fd, " if arg3 =~ ' ' | let arg3 = '\"' . arg3 . '\"' | endif\n");
Bram Moolenaar12365ce2018-05-13 14:45:25 +02001210 fprintf(fd, " let arg3 = substitute(arg3, '!', '\\!', 'g')\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001211
1212 /* If the path has a space: When using cmd.exe (Win NT/2000/XP) put
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001213 * quotes around the diff command and rely on the default value of
Bram Moolenaar792f0e32018-02-27 17:27:13 +01001214 * shellxquote to solve the quoting problem for the whole command.
1215 *
Bram Moolenaar33aec762006-01-22 23:30:12 +00001216 * Otherwise put a double quote just before the space and at the
1217 * end of the command. Putting quotes around the whole thing
1218 * doesn't work on Win 95/98/ME. This is mostly guessed! */
Bram Moolenaar33aec762006-01-22 23:30:12 +00001219 fprintf(fd, " if $VIMRUNTIME =~ ' '\n");
1220 fprintf(fd, " if &sh =~ '\\<cmd'\n");
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001221 fprintf(fd, " if empty(&shellxquote)\n");
1222 fprintf(fd, " let l:shxq_sav = ''\n");
1223 fprintf(fd, " set shellxquote&\n");
1224 fprintf(fd, " endif\n");
1225 fprintf(fd, " let cmd = '\"' . $VIMRUNTIME . '\\diff\"'\n");
Bram Moolenaar33aec762006-01-22 23:30:12 +00001226 fprintf(fd, " else\n");
1227 fprintf(fd, " let cmd = substitute($VIMRUNTIME, ' ', '\" ', '') . '\\diff\"'\n");
1228 fprintf(fd, " endif\n");
1229 fprintf(fd, " else\n");
1230 fprintf(fd, " let cmd = $VIMRUNTIME . '\\diff'\n");
1231 fprintf(fd, " endif\n");
Bram Moolenaar12365ce2018-05-13 14:45:25 +02001232 fprintf(fd, " let cmd = substitute(cmd, '!', '\\!', 'g')\n");
Bram Moolenaarc62a6442013-11-21 18:13:37 +01001233 fprintf(fd, " silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3\n");
1234 fprintf(fd, " if exists('l:shxq_sav')\n");
1235 fprintf(fd, " let &shellxquote=l:shxq_sav\n");
1236 fprintf(fd, " endif\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001237 fprintf(fd, "endfunction\n");
1238 fprintf(fd, "\n");
1239 }
1240 fclose(fd);
1241 printf("%s has been written\n", fname);
1242}
1243
1244 static void
1245change_vimrc_choice(int idx)
1246{
1247 if (choices[idx].installfunc != NULL)
1248 {
1249 /* Switch to NOT change or create a vimrc file. */
1250 if (*oldvimrc != NUL)
1251 alloc_text(idx, "Do NOT change startup file %s", oldvimrc);
1252 else
1253 alloc_text(idx, "Do NOT create startup file %s", vimrc);
1254 choices[idx].installfunc = NULL;
1255 choices[idx + 1].active = 0;
1256 choices[idx + 2].active = 0;
1257 choices[idx + 3].active = 0;
1258 }
1259 else
1260 {
1261 /* Switch to change or create a vimrc file. */
1262 if (*oldvimrc != NUL)
1263 alloc_text(idx, "Overwrite startup file %s with:", oldvimrc);
1264 else
1265 alloc_text(idx, "Create startup file %s with:", vimrc);
1266 choices[idx].installfunc = install_vimrc;
1267 choices[idx + 1].active = 1;
1268 choices[idx + 2].active = 1;
1269 choices[idx + 3].active = 1;
1270 }
1271}
1272
1273/*
1274 * Change the choice how to run Vim.
1275 */
1276 static void
1277change_run_choice(int idx)
1278{
1279 compat_choice = get_choice(compat_choices, TABLE_SIZE(compat_choices));
1280 alloc_text(idx, compat_text, compat_choices[compat_choice]);
1281}
1282
1283/*
1284 * Change the choice if keys are to be remapped.
1285 */
1286 static void
1287change_remap_choice(int idx)
1288{
1289 remap_choice = get_choice(remap_choices, TABLE_SIZE(remap_choices));
1290 alloc_text(idx, remap_text, remap_choices[remap_choice]);
1291}
1292
1293/*
1294 * Change the choice how to select text.
1295 */
1296 static void
1297change_mouse_choice(int idx)
1298{
1299 mouse_choice = get_choice(mouse_choices, TABLE_SIZE(mouse_choices));
1300 alloc_text(idx, mouse_text, mouse_choices[mouse_choice]);
1301}
1302
1303 static void
1304init_vimrc_choices(void)
1305{
1306 /* set path for a new _vimrc file (also when not used) */
1307 strcpy(vimrc, installdir);
1308 strcpy(vimrc + runtimeidx, "_vimrc");
1309
1310 /* Set opposite value and then toggle it by calling change_vimrc_choice() */
1311 if (*oldvimrc == NUL)
1312 choices[choice_count].installfunc = NULL;
1313 else
1314 choices[choice_count].installfunc = install_vimrc;
1315 choices[choice_count].text = NULL;
1316 change_vimrc_choice(choice_count);
1317 choices[choice_count].changefunc = change_vimrc_choice;
1318 choices[choice_count].active = 1;
1319 ++choice_count;
1320
1321 /* default way to run Vim */
1322 alloc_text(choice_count, compat_text, compat_choices[compat_choice]);
1323 choices[choice_count].changefunc = change_run_choice;
1324 choices[choice_count].installfunc = NULL;
1325 choices[choice_count].active = (*oldvimrc == NUL);
1326 ++choice_count;
1327
1328 /* Whether to remap keys */
1329 alloc_text(choice_count, remap_text , remap_choices[remap_choice]);
1330 choices[choice_count].changefunc = change_remap_choice;
Bram Moolenaar945ec092016-06-08 21:17:43 +02001331 choices[choice_count].installfunc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001332 choices[choice_count].active = (*oldvimrc == NUL);
1333 ++choice_count;
1334
1335 /* default way to use the mouse */
1336 alloc_text(choice_count, mouse_text, mouse_choices[mouse_choice]);
1337 choices[choice_count].changefunc = change_mouse_choice;
Bram Moolenaar945ec092016-06-08 21:17:43 +02001338 choices[choice_count].installfunc = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001339 choices[choice_count].active = (*oldvimrc == NUL);
1340 ++choice_count;
1341}
1342
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001343 static LONG
1344reg_create_key(
1345 HKEY root,
1346 const char *subkey,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001347 PHKEY phKey,
1348 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001349{
1350 DWORD disp;
1351
1352 *phKey = NULL;
1353 return RegCreateKeyEx(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001354 root, subkey,
1355 0, NULL, REG_OPTION_NON_VOLATILE,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001356 flag | KEY_WRITE,
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001357 NULL, phKey, &disp);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001358}
1359
1360 static LONG
1361reg_set_string_value(
1362 HKEY hKey,
1363 const char *value_name,
1364 const char *data)
1365{
1366 return RegSetValueEx(hKey, value_name, 0, REG_SZ,
1367 (LPBYTE)data, (DWORD)(1 + strlen(data)));
1368}
1369
1370 static LONG
1371reg_create_key_and_value(
1372 HKEY hRootKey,
1373 const char *subkey,
1374 const char *value_name,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001375 const char *data,
1376 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001377{
1378 HKEY hKey;
Bram Moolenaar6199d432017-10-14 19:05:44 +02001379 LONG lRet = reg_create_key(hRootKey, subkey, &hKey, flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001380
1381 if (ERROR_SUCCESS == lRet)
1382 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001383 lRet = reg_set_string_value(hKey, value_name, data);
1384 RegCloseKey(hKey);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001385 }
1386 return lRet;
1387}
1388
1389 static LONG
1390register_inproc_server(
1391 HKEY hRootKey,
1392 const char *clsid,
1393 const char *extname,
1394 const char *module,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001395 const char *threading_model,
1396 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001397{
1398 CHAR subkey[BUFSIZE];
1399 LONG lRet;
1400
1401 sprintf(subkey, "CLSID\\%s", clsid);
Bram Moolenaar6199d432017-10-14 19:05:44 +02001402 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, extname, flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001403 if (ERROR_SUCCESS == lRet)
1404 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001405 sprintf(subkey, "CLSID\\%s\\InProcServer32", clsid);
Bram Moolenaar6199d432017-10-14 19:05:44 +02001406 lRet = reg_create_key_and_value(hRootKey, subkey, NULL, module, flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001407 if (ERROR_SUCCESS == lRet)
1408 {
1409 lRet = reg_create_key_and_value(hRootKey, subkey,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001410 "ThreadingModel", threading_model, flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001411 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001412 }
1413 return lRet;
1414}
1415
1416 static LONG
1417register_shellex(
1418 HKEY hRootKey,
1419 const char *clsid,
1420 const char *name,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001421 const char *exe_path,
1422 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001423{
1424 LONG lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001425 hRootKey,
1426 "*\\shellex\\ContextMenuHandlers\\gvim",
1427 NULL,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001428 clsid,
1429 flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001430
1431 if (ERROR_SUCCESS == lRet)
1432 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001433 lRet = reg_create_key_and_value(
1434 HKEY_LOCAL_MACHINE,
1435 "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1436 clsid,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001437 name,
1438 flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001439
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001440 if (ERROR_SUCCESS == lRet)
1441 {
1442 lRet = reg_create_key_and_value(
1443 HKEY_LOCAL_MACHINE,
1444 "Software\\Vim\\Gvim",
1445 "path",
Bram Moolenaar6199d432017-10-14 19:05:44 +02001446 exe_path,
1447 flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001448 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001449 }
1450 return lRet;
1451}
1452
1453 static LONG
1454register_openwith(
1455 HKEY hRootKey,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001456 const char *exe_path,
1457 DWORD flag)
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001458{
Bram Moolenaar78050042010-07-31 20:53:54 +02001459 char exe_cmd[BUFSIZE];
1460 LONG lRet;
1461
Bram Moolenaarbbdcb482010-08-02 20:45:27 +02001462 sprintf(exe_cmd, "\"%s\" \"%%1\"", exe_path);
Bram Moolenaar78050042010-07-31 20:53:54 +02001463 lRet = reg_create_key_and_value(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001464 hRootKey,
1465 "Applications\\gvim.exe\\shell\\edit\\command",
1466 NULL,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001467 exe_cmd,
1468 flag);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001469
1470 if (ERROR_SUCCESS == lRet)
1471 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001472 int i;
1473 static const char *openwith[] = {
1474 ".htm\\OpenWithList\\gvim.exe",
1475 ".vim\\OpenWithList\\gvim.exe",
1476 "*\\OpenWithList\\gvim.exe",
1477 };
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001478
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001479 for (i = 0; ERROR_SUCCESS == lRet
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001480 && i < sizeof(openwith) / sizeof(openwith[0]); i++)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001481 {
Bram Moolenaar6199d432017-10-14 19:05:44 +02001482 lRet = reg_create_key_and_value(hRootKey, openwith[i], NULL, "", flag);
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001483 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001484 }
1485
1486 return lRet;
1487}
1488
1489 static LONG
1490register_uninstall(
1491 HKEY hRootKey,
1492 const char *appname,
1493 const char *display_name,
1494 const char *uninstall_string)
1495{
1496 LONG lRet = reg_create_key_and_value(hRootKey, appname,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001497 "DisplayName", display_name, KEY_WOW64_64KEY);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001498
1499 if (ERROR_SUCCESS == lRet)
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001500 lRet = reg_create_key_and_value(hRootKey, appname,
Bram Moolenaar6199d432017-10-14 19:05:44 +02001501 "UninstallString", uninstall_string, KEY_WOW64_64KEY);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001502 return lRet;
1503}
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001504
Bram Moolenaar071d4272004-06-13 20:20:40 +00001505/*
1506 * Add some entries to the registry:
1507 * - to add "Edit with Vim" to the context * menu
1508 * - to add Vim to the "Open with..." list
1509 * - to uninstall Vim
1510 */
1511/*ARGSUSED*/
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001512 static int
Bram Moolenaar071d4272004-06-13 20:20:40 +00001513install_registry(void)
1514{
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001515 LONG lRet = ERROR_SUCCESS;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001516 const char *vim_ext_ThreadingModel = "Apartment";
1517 const char *vim_ext_name = "Vim Shell Extension";
1518 const char *vim_ext_clsid = "{51EEE242-AD87-11d3-9C1E-0090278BBD99}";
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001519 char vim_exe_path[BUFSIZE];
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001520 char display_name[BUFSIZE];
1521 char uninstall_string[BUFSIZE];
Bram Moolenaar6199d432017-10-14 19:05:44 +02001522 int i;
1523 int loop_count = is_64bit_os() ? 2 : 1;
1524 DWORD flag;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001525
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001526 sprintf(vim_exe_path, "%s\\gvim.exe", installdir);
1527
1528 if (install_popup)
1529 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001530 char bufg[BUFSIZE];
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001531
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001532 printf("Creating \"Edit with Vim\" popup menu entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001533
Bram Moolenaar6199d432017-10-14 19:05:44 +02001534 for (i = 0; i < loop_count; i++)
1535 {
1536 if (i == 0)
1537 {
1538 sprintf(bufg, "%s\\" GVIMEXT32_PATH, installdir);
1539 flag = KEY_WOW64_32KEY;
1540 }
1541 else
1542 {
1543 sprintf(bufg, "%s\\" GVIMEXT64_PATH, installdir);
1544 flag = KEY_WOW64_64KEY;
1545 }
1546
1547 lRet = register_inproc_server(
1548 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name,
1549 bufg, vim_ext_ThreadingModel, flag);
1550 if (ERROR_SUCCESS != lRet)
1551 return FAIL;
1552 lRet = register_shellex(
1553 HKEY_CLASSES_ROOT, vim_ext_clsid, vim_ext_name,
1554 vim_exe_path, flag);
1555 if (ERROR_SUCCESS != lRet)
1556 return FAIL;
1557 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001558 }
1559
1560 if (install_openwith)
1561 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001562 printf("Creating \"Open with ...\" list entry\n");
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001563
Bram Moolenaar6199d432017-10-14 19:05:44 +02001564 for (i = 0; i < loop_count; i++)
1565 {
1566 if (i == 0)
1567 flag = KEY_WOW64_32KEY;
1568 else
1569 flag = KEY_WOW64_64KEY;
1570
1571 lRet = register_openwith(HKEY_CLASSES_ROOT, vim_exe_path, flag);
1572 if (ERROR_SUCCESS != lRet)
1573 return FAIL;
1574 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001575 }
1576
1577 printf("Creating an uninstall entry\n");
1578
1579 /* For the NSIS installer use the generated uninstaller. */
1580 if (interactive)
1581 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001582 sprintf(display_name, "Vim " VIM_VERSION_SHORT);
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001583 sprintf(uninstall_string, "%s\\uninstal.exe", installdir);
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001584 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001585 else
1586 {
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001587 sprintf(display_name, "Vim " VIM_VERSION_SHORT " (self-installing)");
Bram Moolenaar16d79a32010-07-18 22:33:56 +02001588 sprintf(uninstall_string, "%s\\uninstall-gui.exe", installdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001589 }
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001590
1591 lRet = register_uninstall(
Bram Moolenaarcc448b32010-07-14 16:52:17 +02001592 HKEY_LOCAL_MACHINE,
1593 "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT,
1594 display_name,
1595 uninstall_string);
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001596 if (ERROR_SUCCESS != lRet)
1597 return FAIL;
Bram Moolenaarccd9ccf2010-07-07 13:19:55 +02001598
Bram Moolenaarab8205e2010-07-07 15:14:03 +02001599 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001600}
1601
1602 static void
1603change_popup_choice(int idx)
1604{
1605 if (install_popup == 0)
1606 {
1607 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";
1608 install_popup = 1;
1609 }
1610 else
1611 {
1612 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";
1613 install_popup = 0;
1614 }
1615}
1616
1617/*
1618 * Only add the choice for the popup menu entry when gvim.exe was found and
1619 * both gvimext.dll and regedit.exe exist.
1620 */
1621 static void
1622init_popup_choice(void)
1623{
1624 struct stat st;
1625
1626 if (has_gvim
Bram Moolenaar6199d432017-10-14 19:05:44 +02001627 && (stat(GVIMEXT32_PATH, &st) >= 0
1628 || stat(GVIMEXT64_PATH, &st) >= 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001629 {
1630 choices[choice_count].changefunc = change_popup_choice;
1631 choices[choice_count].installfunc = NULL;
1632 choices[choice_count].active = 1;
1633 change_popup_choice(choice_count); /* set the text */
1634 ++choice_count;
1635 }
1636 else
1637 add_dummy_choice();
1638}
1639
1640 static void
1641change_openwith_choice(int idx)
1642{
1643 if (install_openwith == 0)
1644 {
1645 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";
1646 install_openwith = 1;
1647 }
1648 else
1649 {
1650 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";
1651 install_openwith = 0;
1652 }
1653}
1654
1655/*
1656 * Only add the choice for the open-with menu entry when gvim.exe was found
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001657 * and regedit.exe exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001658 */
1659 static void
1660init_openwith_choice(void)
1661{
Bram Moolenaar6199d432017-10-14 19:05:44 +02001662 if (has_gvim)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001663 {
1664 choices[choice_count].changefunc = change_openwith_choice;
1665 choices[choice_count].installfunc = NULL;
1666 choices[choice_count].active = 1;
1667 change_openwith_choice(choice_count); /* set the text */
1668 ++choice_count;
1669 }
1670 else
1671 add_dummy_choice();
1672}
1673
Bram Moolenaar071d4272004-06-13 20:20:40 +00001674/* create_shortcut
1675 *
1676 * Create a shell link.
1677 *
1678 * returns 0 on failure, non-zero on successful completion.
1679 *
1680 * NOTE: Currently untested with mingw.
1681 */
1682 int
1683create_shortcut(
1684 const char *shortcut_name,
1685 const char *iconfile_path,
1686 int iconindex,
1687 const char *shortcut_target,
1688 const char *shortcut_args,
1689 const char *workingdir
1690 )
1691{
1692 IShellLink *shelllink_ptr;
1693 HRESULT hres;
1694 IPersistFile *persistfile_ptr;
1695
1696 /* Initialize COM library */
1697 hres = CoInitialize(NULL);
1698 if (!SUCCEEDED(hres))
1699 {
1700 printf("Error: Could not open the COM library. Not creating shortcut.\n");
1701 return FAIL;
1702 }
1703
1704 /* Instantiate a COM object for the ShellLink, store a pointer to it
1705 * in shelllink_ptr. */
1706 hres = CoCreateInstance(&CLSID_ShellLink,
1707 NULL,
1708 CLSCTX_INPROC_SERVER,
1709 &IID_IShellLink,
1710 (void **) &shelllink_ptr);
1711
1712 if (SUCCEEDED(hres)) /* If the instantiation was successful... */
1713 {
1714 /* ...Then build a PersistFile interface for the ShellLink so we can
1715 * save it as a file after we build it. */
1716 hres = shelllink_ptr->lpVtbl->QueryInterface(shelllink_ptr,
1717 &IID_IPersistFile, (void **) &persistfile_ptr);
1718
1719 if (SUCCEEDED(hres))
1720 {
1721 wchar_t wsz[BUFSIZE];
1722
1723 /* translate the (possibly) multibyte shortcut filename to windows
1724 * Unicode so it can be used as a file name.
1725 */
1726 MultiByteToWideChar(CP_ACP, 0, shortcut_name, -1, wsz, BUFSIZE);
1727
1728 /* set the attributes */
1729 shelllink_ptr->lpVtbl->SetPath(shelllink_ptr, shortcut_target);
1730 shelllink_ptr->lpVtbl->SetWorkingDirectory(shelllink_ptr,
1731 workingdir);
1732 shelllink_ptr->lpVtbl->SetIconLocation(shelllink_ptr,
1733 iconfile_path, iconindex);
1734 shelllink_ptr->lpVtbl->SetArguments(shelllink_ptr, shortcut_args);
1735
1736 /* save the shortcut to a file and return the PersistFile object*/
1737 persistfile_ptr->lpVtbl->Save(persistfile_ptr, wsz, 1);
1738 persistfile_ptr->lpVtbl->Release(persistfile_ptr);
1739 }
1740 else
1741 {
1742 printf("QueryInterface Error\n");
1743 return FAIL;
1744 }
1745
1746 /* Return the ShellLink object */
1747 shelllink_ptr->lpVtbl->Release(shelllink_ptr);
1748 }
1749 else
1750 {
1751 printf("CoCreateInstance Error - hres = %08x\n", (int)hres);
1752 return FAIL;
1753 }
1754
1755 return OK;
1756}
1757
1758/*
1759 * Build a path to where we will put a specified link.
1760 *
1761 * Return 0 on error, non-zero on success
1762 */
1763 int
1764build_link_name(
1765 char *link_path,
1766 const char *link_name,
1767 const char *shell_folder_name)
1768{
1769 char shell_folder_path[BUFSIZE];
1770
1771 if (get_shell_folder_path(shell_folder_path, shell_folder_name) == FAIL)
1772 {
1773 printf("An error occurred while attempting to find the path to %s.\n",
1774 shell_folder_name);
1775 return FAIL;
1776 }
1777
1778 /* Make sure the directory exists (create Start Menu\Programs\Vim).
1779 * Ignore errors if it already exists. */
1780 vim_mkdir(shell_folder_path, 0755);
1781
1782 /* build the path to the shortcut and the path to gvim.exe */
1783 sprintf(link_path, "%s\\%s.lnk", shell_folder_path, link_name);
1784
1785 return OK;
1786}
1787
1788 static int
1789build_shortcut(
1790 const char *name, /* Name of the shortcut */
1791 const char *exename, /* Name of the executable (e.g., vim.exe) */
1792 const char *args,
1793 const char *shell_folder,
1794 const char *workingdir)
1795{
1796 char executable_path[BUFSIZE];
1797 char link_name[BUFSIZE];
1798
1799 sprintf(executable_path, "%s\\%s", installdir, exename);
1800
1801 if (build_link_name(link_name, name, shell_folder) == FAIL)
1802 {
1803 printf("An error has occurred. A shortcut to %s will not be created %s.\n",
1804 name,
1805 *shell_folder == 'd' ? "on the desktop" : "in the Start menu");
1806 return FAIL;
1807 }
1808
1809 /* Create the shortcut: */
1810 return create_shortcut(link_name, executable_path, 0,
1811 executable_path, args, workingdir);
1812}
1813
1814/*
1815 * We used to use "homedir" as the working directory, but that is a bad choice
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001816 * on multi-user systems. However, not specifying a directory results in the
1817 * current directory to be c:\Windows\system32 on Windows 7. Use environment
1818 * variables instead.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001819 */
Bram Moolenaar03e228a2013-11-07 04:49:27 +01001820#define WORKDIR "%HOMEDRIVE%%HOMEPATH%"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001821
1822/*
1823 * Create shortcut(s) in the Start Menu\Programs\Vim folder.
1824 */
1825 static void
1826install_start_menu(int idx)
1827{
1828 need_uninstall_entry = 1;
1829 printf("Creating start menu\n");
1830 if (has_vim)
1831 {
1832 if (build_shortcut("Vim", "vim.exe", "",
1833 VIM_STARTMENU, WORKDIR) == FAIL)
1834 return;
1835 if (build_shortcut("Vim Read-only", "vim.exe", "-R",
1836 VIM_STARTMENU, WORKDIR) == FAIL)
1837 return;
1838 if (build_shortcut("Vim Diff", "vim.exe", "-d",
1839 VIM_STARTMENU, WORKDIR) == FAIL)
1840 return;
1841 }
1842 if (has_gvim)
1843 {
1844 if (build_shortcut("gVim", "gvim.exe", "",
1845 VIM_STARTMENU, WORKDIR) == FAIL)
1846 return;
1847 if (build_shortcut("gVim Easy", "gvim.exe", "-y",
1848 VIM_STARTMENU, WORKDIR) == FAIL)
1849 return;
1850 if (build_shortcut("gVim Read-only", "gvim.exe", "-R",
1851 VIM_STARTMENU, WORKDIR) == FAIL)
1852 return;
1853 if (build_shortcut("gVim Diff", "gvim.exe", "-d",
1854 VIM_STARTMENU, WORKDIR) == FAIL)
1855 return;
1856 }
1857 if (build_shortcut("Uninstall",
1858 interactive ? "uninstal.exe" : "uninstall-gui.exe", "",
1859 VIM_STARTMENU, installdir) == FAIL)
1860 return;
1861 /* For Windows NT the working dir of the vimtutor.bat must be right,
1862 * otherwise gvim.exe won't be found and using gvimbat doesn't work. */
1863 if (build_shortcut("Vim tutor", "vimtutor.bat", "",
1864 VIM_STARTMENU, installdir) == FAIL)
1865 return;
1866 if (build_shortcut("Help", has_gvim ? "gvim.exe" : "vim.exe", "-c h",
1867 VIM_STARTMENU, WORKDIR) == FAIL)
1868 return;
1869 {
1870 char shell_folder_path[BUFSIZE];
1871
1872 /* Creating the URL shortcut works a bit differently... */
1873 if (get_shell_folder_path(shell_folder_path, VIM_STARTMENU) == FAIL)
1874 {
1875 printf("Finding the path of the Start menu failed\n");
1876 return ;
1877 }
1878 add_pathsep(shell_folder_path);
1879 strcat(shell_folder_path, "Vim Online.url");
1880 if (!WritePrivateProfileString("InternetShortcut", "URL",
1881 "http://vim.sf.net/", shell_folder_path))
1882 {
1883 printf("Creating the Vim online URL failed\n");
1884 return;
1885 }
1886 }
1887}
1888
1889 static void
1890toggle_startmenu_choice(int idx)
1891{
1892 if (choices[idx].installfunc == NULL)
1893 {
1894 choices[idx].installfunc = install_start_menu;
1895 choices[idx].text = "Add Vim to the Start menu";
1896 }
1897 else
1898 {
1899 choices[idx].installfunc = NULL;
1900 choices[idx].text = "Do NOT add Vim to the Start menu";
1901 }
1902}
1903
1904/*
1905 * Function to actually create the shortcuts
1906 *
1907 * Currently I am supplying no working directory to the shortcut. This
1908 * means that the initial working dir will be:
1909 * - the location of the shortcut if no file is supplied
1910 * - the location of the file being edited if a file is supplied (ie via
1911 * drag and drop onto the shortcut).
1912 */
1913 void
1914install_shortcut_gvim(int idx)
1915{
1916 /* Create shortcut(s) on the desktop */
1917 if (choices[idx].arg)
1918 {
1919 (void)build_shortcut(icon_names[0], "gvim.exe",
1920 "", "desktop", WORKDIR);
1921 need_uninstall_entry = 1;
1922 }
1923}
1924
1925 void
1926install_shortcut_evim(int idx)
1927{
1928 if (choices[idx].arg)
1929 {
1930 (void)build_shortcut(icon_names[1], "gvim.exe",
1931 "-y", "desktop", WORKDIR);
1932 need_uninstall_entry = 1;
1933 }
1934}
1935
1936 void
1937install_shortcut_gview(int idx)
1938{
1939 if (choices[idx].arg)
1940 {
1941 (void)build_shortcut(icon_names[2], "gvim.exe",
1942 "-R", "desktop", WORKDIR);
1943 need_uninstall_entry = 1;
1944 }
1945}
1946
1947 void
1948toggle_shortcut_choice(int idx)
1949{
1950 char *arg;
1951
1952 if (choices[idx].installfunc == install_shortcut_gvim)
1953 arg = "gVim";
1954 else if (choices[idx].installfunc == install_shortcut_evim)
1955 arg = "gVim Easy";
1956 else
1957 arg = "gVim Read-only";
1958 if (choices[idx].arg)
1959 {
1960 choices[idx].arg = 0;
1961 alloc_text(idx, "Do NOT create a desktop icon for %s", arg);
1962 }
1963 else
1964 {
1965 choices[idx].arg = 1;
1966 alloc_text(idx, "Create a desktop icon for %s", arg);
1967 }
1968}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001969
1970 static void
1971init_startmenu_choice(void)
1972{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001973 /* Start menu */
1974 choices[choice_count].changefunc = toggle_startmenu_choice;
1975 choices[choice_count].installfunc = NULL;
1976 choices[choice_count].active = 1;
1977 toggle_startmenu_choice(choice_count); /* set the text */
1978 ++choice_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001979}
1980
1981/*
1982 * Add the choice for the desktop shortcuts.
1983 */
1984 static void
1985init_shortcut_choices(void)
1986{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001987 /* Shortcut to gvim */
1988 choices[choice_count].text = NULL;
1989 choices[choice_count].arg = 0;
1990 choices[choice_count].active = has_gvim;
1991 choices[choice_count].changefunc = toggle_shortcut_choice;
1992 choices[choice_count].installfunc = install_shortcut_gvim;
1993 toggle_shortcut_choice(choice_count);
1994 ++choice_count;
1995
1996 /* Shortcut to evim */
1997 choices[choice_count].text = NULL;
1998 choices[choice_count].arg = 0;
1999 choices[choice_count].active = has_gvim;
2000 choices[choice_count].changefunc = toggle_shortcut_choice;
2001 choices[choice_count].installfunc = install_shortcut_evim;
2002 toggle_shortcut_choice(choice_count);
2003 ++choice_count;
2004
2005 /* Shortcut to gview */
2006 choices[choice_count].text = NULL;
2007 choices[choice_count].arg = 0;
2008 choices[choice_count].active = has_gvim;
2009 choices[choice_count].changefunc = toggle_shortcut_choice;
2010 choices[choice_count].installfunc = install_shortcut_gview;
2011 toggle_shortcut_choice(choice_count);
2012 ++choice_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002013}
2014
Bram Moolenaar071d4272004-06-13 20:20:40 +00002015/*
2016 * Attempt to register OLE for Vim.
2017 */
2018 static void
2019install_OLE_register(void)
2020{
2021 char register_command_string[BUFSIZE + 30];
2022
2023 printf("\n--- Attempting to register Vim with OLE ---\n");
2024 printf("(There is no message whether this works or not.)\n");
2025
Bram Moolenaar071d4272004-06-13 20:20:40 +00002026 sprintf(register_command_string, "\"%s\\gvim.exe\" -silent -register", installdir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002027 system(register_command_string);
2028}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002029
2030/*
2031 * Remove the last part of directory "path[]" to get its parent, and put the
2032 * result in "to[]".
2033 */
2034 static void
2035dir_remove_last(const char *path, char to[BUFSIZE])
2036{
2037 char c;
2038 long last_char_to_copy;
2039 long path_length = strlen(path);
2040
2041 /* skip the last character just in case it is a '\\' */
2042 last_char_to_copy = path_length - 2;
2043 c = path[last_char_to_copy];
2044
2045 while (c != '\\')
2046 {
2047 last_char_to_copy--;
2048 c = path[last_char_to_copy];
2049 }
2050
2051 strncpy(to, path, (size_t)last_char_to_copy);
2052 to[last_char_to_copy] = NUL;
2053}
2054
2055 static void
2056set_directories_text(int idx)
2057{
2058 if (vimfiles_dir_choice == (int)vimfiles_dir_none)
2059 alloc_text(idx, "Do NOT create plugin directories%s", "");
2060 else
2061 alloc_text(idx, "Create plugin directories: %s",
2062 vimfiles_dir_choices[vimfiles_dir_choice]);
2063}
2064
2065/*
2066 * Change the directory that the vim plugin directories will be created in:
2067 * $HOME, $VIM or nowhere.
2068 */
2069 static void
2070change_directories_choice(int idx)
2071{
2072 int choice_count = TABLE_SIZE(vimfiles_dir_choices);
2073
2074 /* Don't offer the $HOME choice if $HOME isn't set. */
2075 if (getenv("HOME") == NULL)
2076 --choice_count;
2077 vimfiles_dir_choice = get_choice(vimfiles_dir_choices, choice_count);
2078 set_directories_text(idx);
2079}
2080
2081/*
2082 * Create the plugin directories...
2083 */
2084/*ARGSUSED*/
2085 static void
2086install_vimfilesdir(int idx)
2087{
2088 int i;
2089 char *p;
2090 char vimdir_path[BUFSIZE];
2091 char vimfiles_path[BUFSIZE];
2092 char tmp_dirname[BUFSIZE];
2093
2094 /* switch on the location that the user wants the plugin directories
2095 * built in */
2096 switch (vimfiles_dir_choice)
2097 {
2098 case vimfiles_dir_vim:
2099 {
2100 /* Go to the %VIM% directory - check env first, then go one dir
2101 * below installdir if there is no %VIM% environment variable.
2102 * The accuracy of $VIM is checked in inspect_system(), so we
2103 * can be sure it is ok to use here. */
2104 p = getenv("VIM");
2105 if (p == NULL) /* No $VIM in path */
2106 dir_remove_last(installdir, vimdir_path);
2107 else
2108 strcpy(vimdir_path, p);
2109 break;
2110 }
2111 case vimfiles_dir_home:
2112 {
2113 /* Find the $HOME directory. Its existence was already checked. */
2114 p = getenv("HOME");
2115 if (p == NULL)
2116 {
2117 printf("Internal error: $HOME is NULL\n");
2118 p = "c:\\";
2119 }
2120 strcpy(vimdir_path, p);
2121 break;
2122 }
2123 case vimfiles_dir_none:
2124 {
2125 /* Do not create vim plugin directory */
2126 return;
2127 }
2128 }
2129
2130 /* Now, just create the directory. If it already exists, it will fail
2131 * silently. */
2132 sprintf(vimfiles_path, "%s\\vimfiles", vimdir_path);
2133 vim_mkdir(vimfiles_path, 0755);
2134
2135 printf("Creating the following directories in \"%s\":\n", vimfiles_path);
2136 for (i = 0; i < TABLE_SIZE(vimfiles_subdirs); i++)
2137 {
2138 sprintf(tmp_dirname, "%s\\%s", vimfiles_path, vimfiles_subdirs[i]);
2139 printf(" %s", vimfiles_subdirs[i]);
2140 vim_mkdir(tmp_dirname, 0755);
2141 }
2142 printf("\n");
2143}
2144
2145/*
2146 * Add the creation of runtime files to the setup sequence.
2147 */
2148 static void
2149init_directories_choice(void)
2150{
2151 struct stat st;
2152 char tmp_dirname[BUFSIZE];
2153 char *p;
2154
2155 choices[choice_count].text = alloc(150);
2156 choices[choice_count].changefunc = change_directories_choice;
2157 choices[choice_count].installfunc = install_vimfilesdir;
2158 choices[choice_count].active = 1;
2159
2160 /* Check if the "compiler" directory already exists. That's a good
2161 * indication that the plugin directories were already created. */
2162 if (getenv("HOME") != NULL)
2163 {
2164 vimfiles_dir_choice = (int)vimfiles_dir_home;
2165 sprintf(tmp_dirname, "%s\\vimfiles\\compiler", getenv("HOME"));
2166 if (stat(tmp_dirname, &st) == 0)
2167 vimfiles_dir_choice = (int)vimfiles_dir_none;
2168 }
2169 else
2170 {
2171 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2172 p = getenv("VIM");
2173 if (p == NULL) /* No $VIM in path, use the install dir */
2174 dir_remove_last(installdir, tmp_dirname);
2175 else
2176 strcpy(tmp_dirname, p);
2177 strcat(tmp_dirname, "\\vimfiles\\compiler");
2178 if (stat(tmp_dirname, &st) == 0)
2179 vimfiles_dir_choice = (int)vimfiles_dir_none;
2180 }
2181
2182 set_directories_text(choice_count);
2183 ++choice_count;
2184}
2185
2186/*
2187 * Setup the choices and the default values.
2188 */
2189 static void
2190setup_choices(void)
2191{
2192 /* install the batch files */
2193 init_bat_choices();
2194
2195 /* (over) write _vimrc file */
2196 init_vimrc_choices();
2197
2198 /* Whether to add Vim to the popup menu */
2199 init_popup_choice();
2200
2201 /* Whether to add Vim to the "Open With..." menu */
2202 init_openwith_choice();
2203
2204 /* Whether to add Vim to the Start Menu. */
2205 init_startmenu_choice();
2206
2207 /* Whether to add shortcuts to the Desktop. */
2208 init_shortcut_choices();
2209
2210 /* Whether to create the runtime directories. */
2211 init_directories_choice();
2212}
2213
2214 static void
2215print_cmd_line_help(void)
2216{
2217 printf("Vim installer non-interactive command line arguments:\n");
2218 printf("\n");
2219 printf("-create-batfiles [vim gvim evim view gview vimdiff gvimdiff]\n");
2220 printf(" Create .bat files for Vim variants in the Windows directory.\n");
2221 printf("-create-vimrc\n");
2222 printf(" Create a default _vimrc file if one does not already exist.\n");
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02002223 printf("-vimrc-remap [no|win]\n");
2224 printf(" Remap keys when creating a default _vimrc file.\n");
2225 printf("-vimrc-behave [unix|mswin|default]\n");
2226 printf(" Set mouse behavior when creating a default _vimrc file.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227 printf("-install-popup\n");
2228 printf(" Install the Edit-with-Vim context menu entry\n");
2229 printf("-install-openwith\n");
2230 printf(" Add Vim to the \"Open With...\" context menu list\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002231 printf("-add-start-menu");
2232 printf(" Add Vim to the start menu\n");
2233 printf("-install-icons");
2234 printf(" Create icons for gVim executables on the desktop\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002235 printf("-create-directories [vim|home]\n");
2236 printf(" Create runtime directories to drop plugins into; in the $VIM\n");
2237 printf(" or $HOME directory\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002238 printf("-register-OLE");
Bram Moolenaarce0842a2005-07-18 21:58:11 +00002239 printf(" Ignored\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002240 printf("\n");
2241}
2242
2243/*
2244 * Setup installation choices based on command line switches
2245 */
2246 static void
2247command_line_setup_choices(int argc, char **argv)
2248{
2249 int i, j;
2250
2251 for (i = 1; i < argc; i++)
2252 {
2253 if (strcmp(argv[i], "-create-batfiles") == 0)
2254 {
2255 if (i + 1 == argc)
2256 continue;
2257 while (argv[i + 1][0] != '-' && i < argc)
2258 {
2259 i++;
2260 for (j = 1; j < TARGET_COUNT; ++j)
2261 if ((targets[j].exenamearg[0] == 'g' ? has_gvim : has_vim)
2262 && strcmp(argv[i], targets[j].name) == 0)
2263 {
2264 init_bat_choice(j);
2265 break;
2266 }
2267 if (j == TARGET_COUNT)
2268 printf("%s is not a valid choice for -create-batfiles\n",
2269 argv[i]);
2270
2271 if (i + 1 == argc)
2272 break;
2273 }
2274 }
2275 else if (strcmp(argv[i], "-create-vimrc") == 0)
2276 {
2277 /* Setup default vimrc choices. If there is already a _vimrc file,
2278 * it will NOT be overwritten.
2279 */
2280 init_vimrc_choices();
2281 }
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02002282 else if (strcmp(argv[i], "-vimrc-remap") == 0)
2283 {
2284 if (i + 1 == argc)
2285 break;
2286 i++;
2287 if (strcmp(argv[i], "no") == 0)
2288 remap_choice = remap_no;
2289 else if (strcmp(argv[i], "win") == 0)
2290 remap_choice = remap_win;
2291 }
2292 else if (strcmp(argv[i], "-vimrc-behave") == 0)
2293 {
2294 if (i + 1 == argc)
2295 break;
2296 i++;
2297 if (strcmp(argv[i], "unix") == 0)
2298 mouse_choice = mouse_xterm;
2299 else if (strcmp(argv[i], "mswin") == 0)
2300 mouse_choice = mouse_mswin;
2301 else if (strcmp(argv[i], "default") == 0)
2302 mouse_choice = mouse_default;
2303 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002304 else if (strcmp(argv[i], "-install-popup") == 0)
2305 {
2306 init_popup_choice();
2307 }
2308 else if (strcmp(argv[i], "-install-openwith") == 0)
2309 {
2310 init_openwith_choice();
2311 }
2312 else if (strcmp(argv[i], "-add-start-menu") == 0)
2313 {
2314 init_startmenu_choice();
2315 }
2316 else if (strcmp(argv[i], "-install-icons") == 0)
2317 {
2318 init_shortcut_choices();
2319 }
2320 else if (strcmp(argv[i], "-create-directories") == 0)
2321 {
2322 init_directories_choice();
2323 if (argv[i + 1][0] != '-')
2324 {
2325 i++;
2326 if (strcmp(argv[i], "vim") == 0)
2327 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2328 else if (strcmp(argv[i], "home") == 0)
2329 {
2330 if (getenv("HOME") == NULL) /* No $HOME in environment */
2331 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2332 else
2333 vimfiles_dir_choice = (int)vimfiles_dir_home;
2334 }
2335 else
2336 {
2337 printf("Unknown argument for -create-directories: %s\n",
2338 argv[i]);
2339 print_cmd_line_help();
2340 }
2341 }
2342 else /* No choice specified, default to vim directory */
2343 vimfiles_dir_choice = (int)vimfiles_dir_vim;
2344 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002345 else if (strcmp(argv[i], "-register-OLE") == 0)
2346 {
2347 /* This is always done when gvim is found */
2348 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002349 else /* Unknown switch */
2350 {
2351 printf("Got unknown argument argv[%d] = %s\n", i, argv[i]);
2352 print_cmd_line_help();
2353 }
2354 }
2355}
2356
2357
2358/*
2359 * Show a few screens full of helpful information.
2360 */
2361 static void
2362show_help(void)
2363{
2364 static char *(items[]) =
2365 {
2366"Installing .bat files\n"
2367"---------------------\n"
2368"The vim.bat file is written in one of the directories in $PATH.\n"
2369"This makes it possible to start Vim from the command line.\n"
2370"If vim.exe can be found in $PATH, the choice for vim.bat will not be\n"
2371"present. It is assumed you will use the existing vim.exe.\n"
2372"If vim.bat can already be found in $PATH this is probably for an old\n"
2373"version of Vim (but this is not checked!). You can overwrite it.\n"
2374"If no vim.bat already exists, you can select one of the directories in\n"
2375"$PATH for creating the batch file, or disable creating a vim.bat file.\n"
2376"\n"
2377"If you choose not to create the vim.bat file, Vim can still be executed\n"
2378"in other ways, but not from the command line.\n"
2379"\n"
2380"The same applies to choices for gvim, evim, (g)view, and (g)vimdiff.\n"
2381"The first item can be used to change the path for all of them.\n"
2382,
2383"Creating a _vimrc file\n"
2384"----------------------\n"
2385"The _vimrc file is used to set options for how Vim behaves.\n"
2386"The install program can create a _vimrc file with a few basic choices.\n"
2387"You can edit this file later to tune your preferences.\n"
2388"If you already have a _vimrc or .vimrc file it can be overwritten.\n"
2389"Don't do that if you have made changes to it.\n"
2390,
2391"Vim features\n"
2392"------------\n"
2393"(this choice is only available when creating a _vimrc file)\n"
2394"1. Vim can run in Vi-compatible mode. Many nice Vim features are then\n"
2395" disabled. In the not-Vi-compatible mode Vim is still mostly Vi\n"
2396" compatible, but adds nice features like multi-level undo. Only\n"
2397" choose Vi-compatible if you really need full Vi compatibility.\n"
2398"2. Running Vim with some enhancements is useful when you want some of\n"
2399" the nice Vim features, but have a slow computer and want to keep it\n"
2400" really fast.\n"
2401"3. Syntax highlighting shows many files in color. Not only does this look\n"
2402" nice, it also makes it easier to spot errors and you can work faster.\n"
2403" The other features include editing compressed files.\n"
2404,
2405"Windows key mapping\n"
2406"-------------------\n"
2407"(this choice is only available when creating a _vimrc file)\n"
2408"Under MS-Windows the CTRL-C key copies text to the clipboard and CTRL-V\n"
2409"pastes text from the clipboard. There are a few more keys like these.\n"
2410"Unfortunately, in Vim these keys normally have another meaning.\n"
2411"1. Choose to have the keys like they normally are in Vim (useful if you\n"
2412" also use Vim on other systems).\n"
2413"2. Choose to have the keys work like they are used on MS-Windows (useful\n"
2414" if you mostly work on MS-Windows).\n"
2415,
2416"Mouse use\n"
2417"---------\n"
2418"(this choice is only available when creating a _vimrc file)\n"
2419"The right mouse button can be used in two ways:\n"
2420"1. The Unix way is to extend an existing selection. The popup menu is\n"
2421" not available.\n"
2422"2. The MS-Windows way is to show a popup menu, which allows you to\n"
2423" copy/paste text, undo/redo, etc. Extending the selection can still be\n"
2424" done by keeping SHIFT pressed while using the left mouse button\n"
2425,
2426"Edit-with-Vim context menu entry\n"
2427"--------------------------------\n"
2428"(this choice is only available when gvim.exe and gvimext.dll are present)\n"
2429"You can associate different file types with Vim, so that you can (double)\n"
2430"click on a file to edit it with Vim. This means you have to individually\n"
2431"select each file type.\n"
2432"An alternative is the option offered here: Install an \"Edit with Vim\"\n"
2433"entry in the popup menu for the right mouse button. This means you can\n"
2434"edit any file with Vim.\n"
2435,
2436"\"Open With...\" context menu entry\n"
2437"--------------------------------\n"
2438"(this choice is only available when gvim.exe is present)\n"
2439"This option adds Vim to the \"Open With...\" entry in the popup menu for\n"
2440"the right mouse button. This also makes it possible to edit HTML files\n"
2441"directly from Internet Explorer.\n"
2442,
2443"Add Vim to the Start menu\n"
2444"-------------------------\n"
2445"In Windows 95 and later, Vim can be added to the Start menu. This will\n"
2446"create a submenu with an entry for vim, gvim, evim, vimdiff, etc..\n"
2447,
2448"Icons on the desktop\n"
2449"--------------------\n"
2450"(these choices are only available when installing gvim)\n"
2451"In Windows 95 and later, shortcuts (icons) can be created on the Desktop.\n"
2452,
2453"Create plugin directories\n"
2454"-------------------------\n"
2455"Plugin directories allow extending Vim by dropping a file into a directory.\n"
2456"This choice allows creating them in $HOME (if you have a home directory) or\n"
2457"$VIM (used for everybody on the system).\n"
2458,
2459NULL
2460 };
2461 int i;
2462 int c;
2463
2464 rewind(stdin);
2465 printf("\n");
2466 for (i = 0; items[i] != NULL; ++i)
2467 {
Bram Moolenaarc3fdf7f2017-10-28 18:36:48 +02002468 puts(items[i]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002469 printf("Hit Enter to continue, b (back) or q (quit help): ");
2470 c = getchar();
2471 rewind(stdin);
2472 if (c == 'b' || c == 'B')
2473 {
2474 if (i == 0)
2475 --i;
2476 else
2477 i -= 2;
2478 }
2479 if (c == 'q' || c == 'Q')
2480 break;
2481 printf("\n");
2482 }
2483}
2484
2485/*
2486 * Install the choices.
2487 */
2488 static void
2489install(void)
2490{
2491 int i;
2492
2493 /* Install the selected choices. */
2494 for (i = 0; i < choice_count; ++i)
2495 if (choices[i].installfunc != NULL && choices[i].active)
2496 (choices[i].installfunc)(i);
2497
2498 /* Add some entries to the registry, if needed. */
2499 if (install_popup
2500 || install_openwith
2501 || (need_uninstall_entry && interactive)
2502 || !interactive)
2503 install_registry();
2504
Bram Moolenaar071d4272004-06-13 20:20:40 +00002505 /* Register gvim with OLE. */
2506 if (has_gvim)
2507 install_OLE_register();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002508}
2509
2510/*
2511 * request_choice
2512 */
2513 static void
2514request_choice(void)
2515{
2516 int i;
2517
2518 printf("\n\nInstall will do for you:\n");
2519 for (i = 0; i < choice_count; ++i)
2520 if (choices[i].active)
2521 printf("%2d %s\n", i + 1, choices[i].text);
2522 printf("To change an item, enter its number\n\n");
2523 printf("Enter item number, h (help), d (do it) or q (quit): ");
2524}
2525
2526 int
2527main(int argc, char **argv)
2528{
2529 int i;
2530 char buf[BUFSIZE];
2531
2532 /*
2533 * Run interactively if there are no command line arguments.
2534 */
2535 if (argc > 1)
2536 interactive = 0;
2537 else
2538 interactive = 1;
2539
2540 /* Initialize this program. */
2541 do_inits(argv);
2542
Bram Moolenaar071d4272004-06-13 20:20:40 +00002543 if (argc > 1 && strcmp(argv[1], "-uninstall-check") == 0)
2544 {
2545 /* Only check for already installed Vims. Used by NSIS installer. */
Bram Moolenaar442b4222010-05-24 21:34:22 +02002546 i = uninstall_check(1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002547
2548 /* Find the value of $VIM, because NSIS isn't able to do this by
2549 * itself. */
2550 get_vim_env();
2551
2552 /* When nothing found exit quietly. If something found wait for
Bram Moolenaarb230bd52010-05-25 21:02:00 +02002553 * a little while, so that the user can read the messages. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002554 if (i)
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002555 sleep(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002556 exit(0);
2557 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002558
2559 printf("This program sets up the installation of Vim "
2560 VIM_VERSION_MEDIUM "\n\n");
2561
2562 /* Check if the user unpacked the archives properly. */
2563 check_unpack();
2564
Bram Moolenaar071d4272004-06-13 20:20:40 +00002565 /* Check for already installed Vims. */
2566 if (interactive)
Bram Moolenaar442b4222010-05-24 21:34:22 +02002567 uninstall_check(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002568
2569 /* Find out information about the system. */
2570 inspect_system();
2571
2572 if (interactive)
2573 {
2574 /* Setup all the choices. */
2575 setup_choices();
2576
2577 /* Let the user change choices and finally install (or quit). */
2578 for (;;)
2579 {
2580 request_choice();
2581 rewind(stdin);
2582 if (scanf("%99s", buf) == 1)
2583 {
2584 if (isdigit(buf[0]))
2585 {
2586 /* Change a choice. */
2587 i = atoi(buf);
2588 if (i > 0 && i <= choice_count && choices[i - 1].active)
2589 (choices[i - 1].changefunc)(i - 1);
2590 else
2591 printf("\nIllegal choice\n");
2592 }
2593 else if (buf[0] == 'h' || buf[0] == 'H')
2594 {
2595 /* Help */
2596 show_help();
2597 }
2598 else if (buf[0] == 'd' || buf[0] == 'D')
2599 {
2600 /* Install! */
2601 install();
2602 printf("\nThat finishes the installation. Happy Vimming!\n");
2603 break;
2604 }
2605 else if (buf[0] == 'q' || buf[0] == 'Q')
2606 {
2607 /* Quit */
2608 printf("\nExiting without anything done\n");
2609 break;
2610 }
2611 else
2612 printf("\nIllegal choice\n");
2613 }
2614 }
2615 printf("\n");
Bram Moolenaar442b4222010-05-24 21:34:22 +02002616 myexit(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002617 }
2618 else
2619 {
2620 /*
2621 * Run non-interactive - setup according to the command line switches
2622 */
2623 command_line_setup_choices(argc, argv);
2624 install();
Bram Moolenaar442b4222010-05-24 21:34:22 +02002625
2626 /* Avoid that the user has to hit Enter, just wait a little bit to
2627 * allow reading the messages. */
Bram Moolenaarab8205e2010-07-07 15:14:03 +02002628 sleep(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002629 }
2630
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631 return 0;
2632}