blob: 7bdceadcbc075ee6e1f6fd31a19adf509e6a0617 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* 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 <ronaharon@yahoo.com> 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() */
24int _cdecl
25#if defined(FEAT_GUI_W32)
26VimMain
27#else
28 main
29#endif
30 __ARGS((int argc, char **argv));
31int (_cdecl *pmain)(int, char **);
32
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +000033#ifdef FEAT_MBYTE
34/* The commandline arguments in UCS2. */
35static DWORD nArgsW = 0;
36static LPWSTR *ArglistW = NULL;
37static int global_argc;
38static char **global_argv;
39
40static int used_file_argc = 0; /* last argument in global_argv[] used
41 for the argument list. */
42static int *used_file_indexes = NULL; /* indexes in global_argv[] for
43 command line arguments added to
44 the argument list */
45static int used_file_count = 0; /* nr of entries in used_file_indexes */
46static int used_file_literal = FALSE; /* take file names literally */
47static int used_file_full_path = FALSE; /* file name was full path */
48static int used_alist_count = 0;
49#endif
50
Bram Moolenaar071d4272004-06-13 20:20:40 +000051#ifndef PROTO
52#ifdef FEAT_GUI
53#ifndef VIMDLL
54void _cdecl SaveInst(HINSTANCE hInst);
55#endif
56void (_cdecl *pSaveInst)(HINSTANCE);
57#endif
58
59 int WINAPI
60WinMain(
61 HINSTANCE hInstance,
62 HINSTANCE hPrevInst,
63 LPSTR lpszCmdLine,
64 int nCmdShow)
65{
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +000066 int argc = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000067 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
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +000079 /* 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)
Bram Moolenaar071d4272004-06-13 20:20:40 +000085 {
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +000086 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 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000109 }
110
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000111 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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000129#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);
188errout:
189#endif
190 free(argv);
191 free(tofree);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000192#ifdef FEAT_MBYTE
193 if (ArglistW != NULL)
194 GlobalFree(ArglistW);
195#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196
197 return 0;
198}
199#endif
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000200
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
208used_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
233set_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
244fix_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