1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * GUI support by Robert Webb 5 * 6 * Do ":help uganda" in Vim to read copying and usage conditions. 7 * Do ":help credits" in Vim to see a list of people who contributed. 8 * See README.txt for an overview of the Vim source code. 9 */ 10 /* 11 * Windows GUI: main program (EXE) entry point: 12 * 13 * Ron Aaron <[email protected]> wrote this and the DLL support code. 14 */ 15 #include "vim.h" 16 17 #ifdef __MINGW32__ 18 # ifndef _cdecl 19 # define _cdecl 20 # endif 21 #endif 22 23 /* cproto doesn't create a prototype for main() */ 24 int _cdecl 25 #if defined(FEAT_GUI_W32) 26 VimMain 27 #else 28 main 29 #endif 30 __ARGS((int argc, char **argv)); 31 int (_cdecl *pmain)(int, char **); 32 33 #ifdef FEAT_MBYTE 34 /* The commandline arguments in UCS2. */ 35 static DWORD nArgsW = 0; 36 static LPWSTR *ArglistW = NULL; 37 static int global_argc; 38 static char **global_argv; 39 40 static int used_file_argc = 0; /* last argument in global_argv[] used 41 for the argument list. */ 42 static int *used_file_indexes = NULL; /* indexes in global_argv[] for 43 command line arguments added to 44 the argument list */ 45 static int used_file_count = 0; /* nr of entries in used_file_indexes */ 46 static int used_file_literal = FALSE; /* take file names literally */ 47 static int used_file_full_path = FALSE; /* file name was full path */ 48 static int used_alist_count = 0; 49 #endif 50 51 #ifndef PROTO 52 #ifdef FEAT_GUI 53 #ifndef VIMDLL 54 void _cdecl SaveInst(HINSTANCE hInst); 55 #endif 56 void (_cdecl *pSaveInst)(HINSTANCE); 57 #endif 58 59 int WINAPI 60 WinMain( 61 HINSTANCE hInstance, 62 HINSTANCE hPrevInst, 63 LPSTR lpszCmdLine, 64 int nCmdShow) 65 { 66 int argc = 0; 67 char **argv; 68 char *tofree; 69 char prog[256]; 70 #ifdef VIMDLL 71 char *p; 72 HANDLE hLib; 73 #endif 74 75 /* Ron: added full path name so that the $VIM variable will get set to our 76 * startup path (so the .vimrc file can be found w/o a VIM env. var.) */ 77 GetModuleFileName(NULL, prog, 255); 78 79 /* Separate the command line into arguments. Use the Unicode functions 80 * when possible. When 'encoding' is later changed these are used to 81 * recode the arguments. */ 82 #ifdef FEAT_MBYTE 83 ArglistW = CommandLineToArgvW(GetCommandLineW(), &nArgsW); 84 if (ArglistW != NULL) 85 { 86 argv = malloc((nArgsW + 1) * sizeof(char *)); 87 if (argv != NULL) 88 { 89 int i; 90 91 argv[argc] = NULL; 92 argc = nArgsW; 93 for (i = 0; i < argc; ++i) 94 { 95 int len; 96 97 WideCharToMultiByte_alloc(GetACP(), 0, 98 ArglistW[i], wcslen(ArglistW[i]) + 1, 99 (LPSTR *)&argv[i], &len, 0, 0); 100 if (argv[i] == NULL) 101 { 102 while (i > 0) 103 free(argv[--i]); 104 free(argv); 105 argc = 0; 106 } 107 } 108 } 109 } 110 111 if (argc == 0) 112 #endif 113 { 114 argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree); 115 if (argc == 0) 116 { 117 MessageBox(0, "Could not allocate memory for command line.", 118 "VIM Error", 0); 119 return 0; 120 } 121 } 122 123 #ifdef FEAT_MBYTE 124 global_argc = argc; 125 global_argv = argv; 126 used_file_indexes = malloc(argc * sizeof(int)); 127 #endif 128 129 #ifdef DYNAMIC_GETTEXT 130 /* Initialize gettext library */ 131 dyn_libintl_init(NULL); 132 #endif 133 134 #ifdef VIMDLL 135 // LoadLibrary - get name of dll to load in here: 136 p = strrchr(prog, '\\'); 137 if (p != NULL) 138 { 139 # ifdef DEBUG 140 strcpy(p+1, "vim32d.dll"); 141 # else 142 strcpy(p+1, "vim32.dll"); 143 # endif 144 } 145 hLib = LoadLibrary(prog); 146 if (hLib == NULL) 147 { 148 MessageBox(0, _("Could not load vim32.dll!"), _("VIM Error"), 0); 149 goto errout; 150 } 151 // fix up the function pointers 152 # ifdef FEAT_GUI 153 pSaveInst = GetProcAddress(hLib, (LPCSTR)2); 154 # endif 155 pmain = GetProcAddress(hLib, (LPCSTR)1); 156 if (pmain == NULL) 157 { 158 MessageBox(0, _("Could not fix up function pointers to the DLL!"), 159 _("VIM Error"),0); 160 goto errout; 161 } 162 #else 163 # ifdef FEAT_GUI 164 pSaveInst = SaveInst; 165 # endif 166 pmain = 167 # if defined(FEAT_GUI_W32) 168 //&& defined(__MINGW32__) 169 VimMain 170 # else 171 main 172 # endif 173 ; 174 #endif 175 #ifdef FEAT_GUI 176 pSaveInst( 177 #ifdef __MINGW32__ 178 GetModuleHandle(NULL) 179 #else 180 hInstance 181 #endif 182 ); 183 #endif 184 pmain(argc, argv); 185 186 #ifdef VIMDLL 187 FreeLibrary(hLib); 188 errout: 189 #endif 190 free(argv); 191 free(tofree); 192 #ifdef FEAT_MBYTE 193 if (ArglistW != NULL) 194 GlobalFree(ArglistW); 195 #endif 196 197 return 0; 198 } 199 #endif 200 201 #ifdef FEAT_MBYTE 202 /* 203 * Remember "name" is an argument that was added to the argument list. 204 * This avoids that we have to re-parse the argument list when fix_arg_enc() 205 * is called. 206 */ 207 void 208 used_file_arg(name, literal, full_path) 209 char *name; 210 int literal; 211 int full_path; 212 { 213 int i; 214 215 if (used_file_indexes == NULL) 216 return; 217 for (i = used_file_argc + 1; i < global_argc; ++i) 218 if (STRCMP(global_argv[i], name) == 0) 219 { 220 used_file_argc = i; 221 used_file_indexes[used_file_count++] = i; 222 break; 223 } 224 used_file_literal = literal; 225 used_file_full_path = full_path; 226 } 227 228 /* 229 * Remember the length of the argument list as it was. If it changes then we 230 * leave it alone when 'encoding' is set. 231 */ 232 void 233 set_alist_count(void) 234 { 235 used_alist_count = GARGCOUNT; 236 } 237 238 /* 239 * Fix the encoding of the command line arguments. Invoked when 'encoding' 240 * has been changed while starting up. Use the UCS-2 command line arguments 241 * and convert them to 'encoding'. 242 */ 243 void 244 fix_arg_enc() 245 { 246 int i; 247 int idx; 248 char_u *str; 249 250 /* Safety checks: 251 * - if argument count differs between the wide and non-wide argument 252 * list, something must be wrong. 253 * - the file name arguments must have been located. 254 * - the length of the argument list wasn't changed by the user. 255 */ 256 if (global_argc != (int)nArgsW 257 || ArglistW == NULL 258 || used_file_indexes == NULL 259 || used_file_count == 0 260 || used_alist_count != GARGCOUNT) 261 return; 262 263 /* Clear the argument list. Make room for the new arguments. */ 264 alist_clear(&global_alist); 265 if (ga_grow(&global_alist.al_ga, used_file_count) == FAIL) 266 return; /* out of memory */ 267 268 for (i = 0; i < used_file_count; ++i) 269 { 270 idx = used_file_indexes[i]; 271 str = ucs2_to_enc(ArglistW[idx], NULL); 272 if (str != NULL) 273 alist_add(&global_alist, str, used_file_literal ? 2 : 0); 274 } 275 276 if (!used_file_literal) 277 { 278 /* Now expand wildcards in the arguments. */ 279 /* Temporarily add '(' and ')' to 'isfname'. These are valid 280 * filename characters but are excluded from 'isfname' to make 281 * "gf" work on a file name in parenthesis (e.g.: see vim.h). */ 282 do_cmdline_cmd((char_u *)":let SaVe_ISF = &isf|set isf+=(,)"); 283 alist_expand(); 284 do_cmdline_cmd((char_u *)":let &isf = SaVe_ISF|unlet SaVe_ISF"); 285 } 286 287 /* If wildcard expansion failed, we are editing the first file of the 288 * arglist and there is no file name: Edit the first argument now. */ 289 if (curwin->w_arg_idx == 0 && curbuf->b_fname == NULL) 290 { 291 do_cmdline_cmd((char_u *)":rewind"); 292 if (GARGCOUNT == 1 && used_file_full_path) 293 (void)vim_chdirfile(alist_name(&GARGLIST[0])); 294 } 295 } 296 #endif 297 298