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