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