diff options
Diffstat (limited to 'src/os_w32exe.c')
-rw-r--r-- | src/os_w32exe.c | 173 |
1 files changed, 167 insertions, 6 deletions
diff --git a/src/os_w32exe.c b/src/os_w32exe.c index e37873b76..7bdceadcb 100644 --- a/src/os_w32exe.c +++ b/src/os_w32exe.c @@ -30,6 +30,24 @@ VimMain __ARGS((int argc, char **argv)); int (_cdecl *pmain)(int, char **); +#ifdef FEAT_MBYTE +/* The commandline arguments in UCS2. */ +static DWORD nArgsW = 0; +static LPWSTR *ArglistW = NULL; +static int global_argc; +static char **global_argv; + +static int used_file_argc = 0; /* last argument in global_argv[] used + for the argument list. */ +static int *used_file_indexes = NULL; /* indexes in global_argv[] for + command line arguments added to + the argument list */ +static int used_file_count = 0; /* nr of entries in used_file_indexes */ +static int used_file_literal = FALSE; /* take file names literally */ +static int used_file_full_path = FALSE; /* file name was full path */ +static int used_alist_count = 0; +#endif + #ifndef PROTO #ifdef FEAT_GUI #ifndef VIMDLL @@ -45,7 +63,7 @@ WinMain( LPSTR lpszCmdLine, int nCmdShow) { - int argc; + int argc = 0; char **argv; char *tofree; char prog[256]; @@ -58,15 +76,56 @@ WinMain( * startup path (so the .vimrc file can be found w/o a VIM env. var.) */ GetModuleFileName(NULL, prog, 255); - /* Separate the command line into arguments. */ - argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree); + /* Separate the command line into arguments. Use the Unicode functions + * when possible. When 'encoding' is later changed these are used to + * recode the arguments. */ +#ifdef FEAT_MBYTE + ArglistW = CommandLineToArgvW(GetCommandLineW(), &nArgsW); + if (ArglistW != NULL) + { + argv = malloc((nArgsW + 1) * sizeof(char *)); + if (argv != NULL) + { + int i; + + argv[argc] = NULL; + argc = nArgsW; + for (i = 0; i < argc; ++i) + { + int len; + + WideCharToMultiByte_alloc(GetACP(), 0, + ArglistW[i], wcslen(ArglistW[i]) + 1, + (LPSTR *)&argv[i], &len, 0, 0); + if (argv[i] == NULL) + { + while (i > 0) + free(argv[--i]); + free(argv); + argc = 0; + } + } + } + } + if (argc == 0) +#endif { - MessageBox(0, _("Could not allocate memory for command line."), - _("VIM Error"), 0); - return 0; + argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree); + if (argc == 0) + { + MessageBox(0, "Could not allocate memory for command line.", + "VIM Error", 0); + return 0; + } } +#ifdef FEAT_MBYTE + global_argc = argc; + global_argv = argv; + used_file_indexes = malloc(argc * sizeof(int)); +#endif + #ifdef DYNAMIC_GETTEXT /* Initialize gettext library */ dyn_libintl_init(NULL); @@ -130,7 +189,109 @@ errout: #endif free(argv); free(tofree); +#ifdef FEAT_MBYTE + if (ArglistW != NULL) + GlobalFree(ArglistW); +#endif return 0; } #endif + +#ifdef FEAT_MBYTE +/* + * Remember "name" is an argument that was added to the argument list. + * This avoids that we have to re-parse the argument list when fix_arg_enc() + * is called. + */ + void +used_file_arg(name, literal, full_path) + char *name; + int literal; + int full_path; +{ + int i; + + if (used_file_indexes == NULL) + return; + for (i = used_file_argc + 1; i < global_argc; ++i) + if (STRCMP(global_argv[i], name) == 0) + { + used_file_argc = i; + used_file_indexes[used_file_count++] = i; + break; + } + used_file_literal = literal; + used_file_full_path = full_path; +} + +/* + * Remember the length of the argument list as it was. If it changes then we + * leave it alone when 'encoding' is set. + */ + void +set_alist_count(void) +{ + used_alist_count = GARGCOUNT; +} + +/* + * Fix the encoding of the command line arguments. Invoked when 'encoding' + * has been changed while starting up. Use the UCS-2 command line arguments + * and convert them to 'encoding'. + */ + void +fix_arg_enc() +{ + int i; + int idx; + char_u *str; + + /* Safety checks: + * - if argument count differs between the wide and non-wide argument + * list, something must be wrong. + * - the file name arguments must have been located. + * - the length of the argument list wasn't changed by the user. + */ + if (global_argc != (int)nArgsW + || ArglistW == NULL + || used_file_indexes == NULL + || used_file_count == 0 + || used_alist_count != GARGCOUNT) + return; + + /* Clear the argument list. Make room for the new arguments. */ + alist_clear(&global_alist); + if (ga_grow(&global_alist.al_ga, used_file_count) == FAIL) + return; /* out of memory */ + + for (i = 0; i < used_file_count; ++i) + { + idx = used_file_indexes[i]; + str = ucs2_to_enc(ArglistW[idx], NULL); + if (str != NULL) + alist_add(&global_alist, str, used_file_literal ? 2 : 0); + } + + if (!used_file_literal) + { + /* Now expand wildcards in the arguments. */ + /* Temporarily add '(' and ')' to 'isfname'. These are valid + * filename characters but are excluded from 'isfname' to make + * "gf" work on a file name in parenthesis (e.g.: see vim.h). */ + do_cmdline_cmd((char_u *)":let SaVe_ISF = &isf|set isf+=(,)"); + alist_expand(); + do_cmdline_cmd((char_u *)":let &isf = SaVe_ISF|unlet SaVe_ISF"); + } + + /* If wildcard expansion failed, we are editing the first file of the + * arglist and there is no file name: Edit the first argument now. */ + if (curwin->w_arg_idx == 0 && curbuf->b_fname == NULL) + { + do_cmdline_cmd((char_u *)":rewind"); + if (GARGCOUNT == 1 && used_file_full_path) + (void)vim_chdirfile(alist_name(&GARGLIST[0])); + } +} +#endif + |