7
|
1 /* vi:set ts=8 sts=4 sw=4:
|
|
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 * os_win16.c
|
|
11 *
|
|
12 * Win16 (Windows 3.1x) system-dependent routines.
|
|
13 * Carved brutally from os_win32.c by Vince Negri <vn@aslnet.co.uk>
|
|
14 */
|
|
15 #ifdef __BORLANDC__
|
|
16 # pragma warn -par
|
|
17 # pragma warn -ucp
|
|
18 # pragma warn -use
|
|
19 # pragma warn -aus
|
|
20 # pragma warn -obs
|
|
21 #endif
|
|
22
|
|
23 #include "vim.h"
|
|
24
|
|
25 #include <dos.h>
|
|
26 #include <string.h>
|
|
27 #include <sys/types.h>
|
|
28 #include <signal.h>
|
|
29 #include <limits.h>
|
|
30 #include <process.h>
|
|
31
|
|
32 #undef chdir
|
|
33 #include <direct.h>
|
|
34 #include <shellapi.h> /* required for FindExecutable() */
|
|
35
|
|
36
|
|
37 /* Record all output and all keyboard & mouse input */
|
|
38 /* #define MCH_WRITE_DUMP */
|
|
39
|
|
40 #ifdef MCH_WRITE_DUMP
|
|
41 FILE* fdDump = NULL;
|
|
42 #endif
|
|
43
|
|
44
|
|
45 /*
|
|
46 * When generating prototypes for Win32 on Unix, these lines make the syntax
|
|
47 * errors disappear. They do not need to be correct.
|
|
48 */
|
|
49 #ifdef PROTO
|
|
50 typedef int HANDLE;
|
|
51 typedef int SMALL_RECT;
|
|
52 typedef int COORD;
|
|
53 typedef int SHORT;
|
|
54 typedef int WORD;
|
|
55 typedef int DWORD;
|
|
56 typedef int BOOL;
|
|
57 typedef int LPSTR;
|
|
58 typedef int LPTSTR;
|
|
59 typedef int KEY_EVENT_RECORD;
|
|
60 typedef int MOUSE_EVENT_RECORD;
|
|
61 # define WINAPI
|
|
62 typedef int CONSOLE_CURSOR_INFO;
|
|
63 typedef char * LPCSTR;
|
|
64 # define WINBASEAPI
|
|
65 typedef int INPUT_RECORD;
|
|
66 # define _cdecl
|
|
67 #endif
|
|
68
|
|
69 #ifdef __BORLANDC__
|
|
70 /* being a more ANSI compliant compiler, BorlandC doesn't define _stricoll:
|
|
71 * but it does in BC 5.02! */
|
|
72 # if __BORLANDC__ < 0x502
|
|
73 int _stricoll(char *a, char *b);
|
|
74 # endif
|
|
75 #endif
|
|
76
|
|
77 /* cproto doesn't create a prototype for main() */
|
|
78 int _cdecl
|
|
79 VimMain
|
|
80 __ARGS((int argc, char **argv));
|
379
|
81 static int (_cdecl *pmain)(int, char **);
|
7
|
82
|
|
83 #ifndef PROTO
|
|
84 void _cdecl SaveInst(HINSTANCE hInst);
|
379
|
85 static void (_cdecl *pSaveInst)(HINSTANCE);
|
7
|
86
|
|
87 int WINAPI
|
|
88 WinMain(
|
|
89 HINSTANCE hInstance,
|
|
90 HINSTANCE hPrevInst,
|
|
91 LPSTR lpszCmdLine,
|
|
92 int nCmdShow)
|
|
93 {
|
|
94 int argc;
|
|
95 char **argv;
|
|
96 char *tofree;
|
|
97 char prog[256];
|
|
98
|
|
99 /*
|
|
100 * Ron: added full path name so that the $VIM variable will get set to our
|
|
101 * startup path (so the .vimrc file can be found w/o a VIM env. var.)
|
|
102 * Remove the ".exe" extension, and find the 1st non-space.
|
|
103 */
|
|
104 GetModuleFileName(hInstance, prog, 255);
|
|
105 if (*prog != NUL)
|
|
106 exe_name = FullName_save((char_u *)prog, FALSE);
|
|
107
|
|
108 /* Separate the command line into arguments. */
|
|
109 argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree);
|
|
110 if (argc == 0)
|
|
111 {
|
|
112 /* Error message? */
|
|
113 return 0;
|
|
114 }
|
|
115
|
|
116 pSaveInst = SaveInst;
|
|
117 pmain = VimMain;
|
|
118 pSaveInst(hInstance);
|
|
119 pmain(argc, argv);
|
|
120
|
|
121 free(argv);
|
1738
|
122 if (tofree != NULL)
|
|
123 free(tofree);
|
7
|
124
|
|
125 return 0;
|
|
126 }
|
|
127 #endif
|
|
128
|
|
129
|
|
130
|
|
131
|
|
132
|
|
133
|
|
134 #ifdef FEAT_MOUSE
|
|
135
|
|
136 /*
|
|
137 * For the GUI the mouse handling is in gui_w32.c.
|
|
138 */
|
|
139 void
|
|
140 mch_setmouse(
|
|
141 int on)
|
|
142 {
|
|
143 }
|
|
144 #endif /* FEAT_MOUSE */
|
|
145
|
|
146
|
|
147
|
|
148 /*
|
|
149 * GUI version of mch_init().
|
|
150 */
|
|
151 void
|
|
152 mch_init()
|
|
153 {
|
|
154 extern int _fmode;
|
|
155
|
|
156
|
|
157 /* Let critical errors result in a failure, not in a dialog box. Required
|
|
158 * for the timestamp test to work on removed floppies. */
|
|
159 SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
160
|
|
161 _fmode = O_BINARY; /* we do our own CR-LF translation */
|
|
162
|
|
163 /* Specify window size. Is there a place to get the default from? */
|
|
164 Rows = 25;
|
|
165 Columns = 80;
|
|
166
|
|
167
|
|
168 set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);
|
|
169
|
|
170 #ifdef FEAT_CLIPBOARD
|
|
171 clip_init(TRUE);
|
|
172
|
|
173 /*
|
|
174 * Vim's own clipboard format recognises whether the text is char, line,
|
|
175 * or rectangular block. Only useful for copying between two Vims.
|
|
176 * "VimClipboard" was used for previous versions, using the first
|
|
177 * character to specify MCHAR, MLINE or MBLOCK.
|
|
178 */
|
|
179 clip_star.format = RegisterClipboardFormat("VimClipboard2");
|
|
180 clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
|
|
181 #endif
|
|
182 }
|
|
183
|
|
184
|
|
185
|
|
186 /*
|
|
187 * Do we have an interactive window?
|
|
188 */
|
|
189 int
|
|
190 mch_check_win(
|
|
191 int argc,
|
|
192 char **argv)
|
|
193 {
|
|
194 return OK; /* GUI always has a tty */
|
|
195 }
|
|
196
|
|
197
|
|
198 /*
|
|
199 * return process ID
|
|
200 */
|
|
201 long
|
|
202 mch_get_pid()
|
|
203 {
|
|
204 return (long)GetCurrentTask();
|
|
205 }
|
|
206
|
|
207
|
|
208 /*
|
|
209 * Specialised version of system().
|
|
210 * This version proceeds as follows:
|
|
211 * 1. Start the program with WinExec
|
|
212 * 2. Wait for the module use count of the program to go to 0
|
|
213 * (This is the best way of detecting the program has finished)
|
|
214 */
|
|
215
|
|
216 static int
|
|
217 mch_system(char *cmd, int options)
|
|
218 {
|
|
219 DWORD ret = 0;
|
|
220 UINT wShowWindow;
|
|
221 UINT h_module;
|
|
222 MSG msg;
|
|
223 BOOL again = TRUE;
|
|
224
|
|
225 /*
|
|
226 * It's nicer to run a filter command in a minimized window, but in
|
|
227 */
|
|
228 if (options & SHELL_DOOUT)
|
|
229 wShowWindow = SW_SHOWMINIMIZED;
|
|
230 else
|
|
231 wShowWindow = SW_SHOWNORMAL;
|
|
232
|
|
233 /* Now, run the command */
|
|
234 h_module = WinExec((LPCSTR)cmd, wShowWindow);
|
|
235
|
|
236 if (h_module < 32)
|
|
237 {
|
|
238 /*error*/
|
|
239 ret = -h_module;
|
|
240 }
|
|
241 else
|
|
242 {
|
|
243 /* Wait for the command to terminate before continuing */
|
|
244 while (GetModuleUsage((HINSTANCE)h_module) > 0 && again )
|
|
245 {
|
|
246 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) && again )
|
|
247 {
|
|
248 if(msg.message == WM_QUIT)
|
|
249
|
|
250 {
|
|
251 PostQuitMessage(msg.wParam);
|
|
252 again = FALSE;
|
|
253 }
|
|
254 TranslateMessage(&msg);
|
|
255 DispatchMessage(&msg);
|
|
256 }
|
|
257 }
|
|
258 }
|
|
259
|
|
260 return ret;
|
|
261 }
|
|
262
|
|
263 /*
|
|
264 * Either execute a command by calling the shell or start a new shell
|
|
265 */
|
|
266 int
|
|
267 mch_call_shell(
|
|
268 char_u *cmd,
|
|
269 int options) /* SHELL_, see vim.h */
|
|
270 {
|
|
271 int x;
|
|
272 int tmode = cur_tmode;
|
|
273
|
|
274 out_flush();
|
|
275
|
|
276
|
|
277 #ifdef MCH_WRITE_DUMP
|
|
278 if (fdDump)
|
|
279 {
|
|
280 fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
|
|
281 fflush(fdDump);
|
|
282 }
|
|
283 #endif
|
|
284
|
|
285 /*
|
|
286 * Catch all deadly signals while running the external command, because a
|
|
287 * CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us.
|
|
288 */
|
|
289 signal(SIGINT, SIG_IGN);
|
|
290 signal(SIGILL, SIG_IGN);
|
|
291 signal(SIGFPE, SIG_IGN);
|
|
292 signal(SIGSEGV, SIG_IGN);
|
|
293 signal(SIGTERM, SIG_IGN);
|
|
294 signal(SIGABRT, SIG_IGN);
|
|
295
|
|
296 if (options & SHELL_COOKED)
|
|
297 settmode(TMODE_COOK); /* set to normal mode */
|
|
298
|
|
299 if (cmd == NULL)
|
|
300 {
|
|
301 x = mch_system(p_sh, options);
|
|
302 }
|
|
303 else
|
|
304 {
|
|
305 /* we use "command" or "cmd" to start the shell; slow but easy */
|
|
306 char_u *newcmd;
|
|
307
|
|
308 newcmd = lalloc(
|
|
309 STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE);
|
|
310 if (newcmd != NULL)
|
|
311 {
|
|
312 if (STRNICMP(cmd, "start ", 6) == 0)
|
|
313 {
|
|
314 sprintf((char *)newcmd, "%s\0", cmd+6);
|
|
315 if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31)
|
|
316 x = 0;
|
|
317 else
|
|
318 x = -1;
|
|
319 }
|
|
320 else
|
|
321 {
|
|
322 sprintf((char *)newcmd, "%s%s %s %s",
|
|
323 "",
|
|
324 p_sh,
|
|
325 p_shcf,
|
|
326 cmd);
|
|
327 x = mch_system((char *)newcmd, options);
|
|
328 }
|
|
329 vim_free(newcmd);
|
|
330 }
|
|
331 }
|
|
332
|
|
333 if (tmode == TMODE_RAW)
|
|
334 settmode(TMODE_RAW); /* set to raw mode */
|
|
335
|
|
336 if (x && !(options & SHELL_SILENT) && !emsg_silent)
|
|
337 {
|
|
338 smsg(_("shell returned %d"), x);
|
|
339 msg_putchar('\n');
|
|
340 }
|
|
341 #ifdef FEAT_TITLE
|
|
342 resettitle();
|
|
343 #endif
|
|
344
|
|
345 signal(SIGINT, SIG_DFL);
|
|
346 signal(SIGILL, SIG_DFL);
|
|
347 signal(SIGFPE, SIG_DFL);
|
|
348 signal(SIGSEGV, SIG_DFL);
|
|
349 signal(SIGTERM, SIG_DFL);
|
|
350 signal(SIGABRT, SIG_DFL);
|
|
351
|
|
352
|
|
353 return x;
|
|
354 }
|
|
355
|
|
356
|
|
357 /*
|
|
358 * Delay for half a second.
|
|
359 */
|
|
360 void
|
|
361 mch_delay(
|
|
362 long msec,
|
|
363 int ignoreinput)
|
|
364 {
|
|
365 #ifdef MUST_FIX
|
|
366 Sleep((int)msec); /* never wait for input */
|
|
367 #endif
|
|
368 }
|
|
369
|
|
370
|
|
371 /*
|
|
372 * check for an "interrupt signal": CTRL-break or CTRL-C
|
|
373 */
|
|
374 void
|
|
375 mch_breakcheck()
|
|
376 {
|
|
377 /* never used */
|
|
378 }
|
|
379
|
|
380
|
|
381 /*
|
|
382 * How much memory is available?
|
|
383 */
|
|
384 long_u
|
|
385 mch_avail_mem(
|
|
386 int special)
|
|
387 {
|
|
388 return GetFreeSpace(0);
|
|
389 }
|
|
390
|
|
391
|
|
392 /*
|
|
393 * Like rename(), returns 0 upon success, non-zero upon failure.
|
|
394 * Should probably set errno appropriately when errors occur.
|
|
395 */
|
|
396 int
|
|
397 mch_rename(
|
|
398 const char *pszOldFile,
|
|
399 const char *pszNewFile)
|
|
400 {
|
|
401
|
|
402 /*
|
|
403 * No need to play tricks, this isn't rubbish like Windows 95 <g>
|
|
404 */
|
|
405 return rename(pszOldFile, pszNewFile);
|
|
406
|
|
407 }
|
|
408
|
|
409 /*
|
|
410 * Get the default shell for the current hardware platform
|
|
411 */
|
|
412 char*
|
|
413 default_shell()
|
|
414 {
|
|
415 char* psz = NULL;
|
|
416
|
|
417 psz = "command.com";
|
|
418
|
|
419 return psz;
|
|
420 }
|