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