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