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);
|
|
124 free(tofree);
|
|
125
|
|
126 return 0;
|
|
127 }
|
|
128 #endif
|
|
129
|
|
130
|
|
131
|
|
132
|
|
133
|
|
134
|
|
135 #ifdef FEAT_MOUSE
|
|
136
|
|
137 /*
|
|
138 * For the GUI the mouse handling is in gui_w32.c.
|
|
139 */
|
|
140 void
|
|
141 mch_setmouse(
|
|
142 int on)
|
|
143 {
|
|
144 }
|
|
145 #endif /* FEAT_MOUSE */
|
|
146
|
|
147
|
|
148
|
|
149 /*
|
|
150 * GUI version of mch_init().
|
|
151 */
|
|
152 void
|
|
153 mch_init()
|
|
154 {
|
|
155 extern int _fmode;
|
|
156
|
|
157
|
|
158 /* Let critical errors result in a failure, not in a dialog box. Required
|
|
159 * for the timestamp test to work on removed floppies. */
|
|
160 SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
161
|
|
162 _fmode = O_BINARY; /* we do our own CR-LF translation */
|
|
163
|
|
164 /* Specify window size. Is there a place to get the default from? */
|
|
165 Rows = 25;
|
|
166 Columns = 80;
|
|
167
|
|
168
|
|
169 set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);
|
|
170
|
|
171 #ifdef FEAT_CLIPBOARD
|
|
172 clip_init(TRUE);
|
|
173
|
|
174 /*
|
|
175 * Vim's own clipboard format recognises whether the text is char, line,
|
|
176 * or rectangular block. Only useful for copying between two Vims.
|
|
177 * "VimClipboard" was used for previous versions, using the first
|
|
178 * character to specify MCHAR, MLINE or MBLOCK.
|
|
179 */
|
|
180 clip_star.format = RegisterClipboardFormat("VimClipboard2");
|
|
181 clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
|
|
182 #endif
|
|
183 }
|
|
184
|
|
185
|
|
186
|
|
187 /*
|
|
188 * Do we have an interactive window?
|
|
189 */
|
|
190 int
|
|
191 mch_check_win(
|
|
192 int argc,
|
|
193 char **argv)
|
|
194 {
|
|
195 int i;
|
|
196
|
|
197 return OK; /* GUI always has a tty */
|
|
198 }
|
|
199
|
|
200
|
|
201 /*
|
|
202 * return process ID
|
|
203 */
|
|
204 long
|
|
205 mch_get_pid()
|
|
206 {
|
|
207 return (long)GetCurrentTask();
|
|
208 }
|
|
209
|
|
210
|
|
211 /*
|
|
212 * Specialised version of system().
|
|
213 * This version proceeds as follows:
|
|
214 * 1. Start the program with WinExec
|
|
215 * 2. Wait for the module use count of the program to go to 0
|
|
216 * (This is the best way of detecting the program has finished)
|
|
217 */
|
|
218
|
|
219 static int
|
|
220 mch_system(char *cmd, int options)
|
|
221 {
|
|
222 DWORD ret = 0;
|
|
223 UINT wShowWindow;
|
|
224 UINT h_module;
|
|
225 MSG msg;
|
|
226 BOOL again = TRUE;
|
|
227
|
|
228 /*
|
|
229 * It's nicer to run a filter command in a minimized window, but in
|
|
230 */
|
|
231 if (options & SHELL_DOOUT)
|
|
232 wShowWindow = SW_SHOWMINIMIZED;
|
|
233 else
|
|
234 wShowWindow = SW_SHOWNORMAL;
|
|
235
|
|
236 /* Now, run the command */
|
|
237 h_module = WinExec((LPCSTR)cmd, wShowWindow);
|
|
238
|
|
239 if (h_module < 32)
|
|
240 {
|
|
241 /*error*/
|
|
242 ret = -h_module;
|
|
243 }
|
|
244 else
|
|
245 {
|
|
246 /* Wait for the command to terminate before continuing */
|
|
247 while (GetModuleUsage((HINSTANCE)h_module) > 0 && again )
|
|
248 {
|
|
249 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) && again )
|
|
250 {
|
|
251 if(msg.message == WM_QUIT)
|
|
252
|
|
253 {
|
|
254 PostQuitMessage(msg.wParam);
|
|
255 again = FALSE;
|
|
256 }
|
|
257 TranslateMessage(&msg);
|
|
258 DispatchMessage(&msg);
|
|
259 }
|
|
260 }
|
|
261 }
|
|
262
|
|
263 return ret;
|
|
264 }
|
|
265
|
|
266 /*
|
|
267 * Either execute a command by calling the shell or start a new shell
|
|
268 */
|
|
269 int
|
|
270 mch_call_shell(
|
|
271 char_u *cmd,
|
|
272 int options) /* SHELL_, see vim.h */
|
|
273 {
|
|
274 int x;
|
|
275 int tmode = cur_tmode;
|
|
276
|
|
277 out_flush();
|
|
278
|
|
279
|
|
280 #ifdef MCH_WRITE_DUMP
|
|
281 if (fdDump)
|
|
282 {
|
|
283 fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
|
|
284 fflush(fdDump);
|
|
285 }
|
|
286 #endif
|
|
287
|
|
288 /*
|
|
289 * Catch all deadly signals while running the external command, because a
|
|
290 * CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us.
|
|
291 */
|
|
292 signal(SIGINT, SIG_IGN);
|
|
293 signal(SIGILL, SIG_IGN);
|
|
294 signal(SIGFPE, SIG_IGN);
|
|
295 signal(SIGSEGV, SIG_IGN);
|
|
296 signal(SIGTERM, SIG_IGN);
|
|
297 signal(SIGABRT, SIG_IGN);
|
|
298
|
|
299 if (options & SHELL_COOKED)
|
|
300 settmode(TMODE_COOK); /* set to normal mode */
|
|
301
|
|
302 if (cmd == NULL)
|
|
303 {
|
|
304 x = mch_system(p_sh, options);
|
|
305 }
|
|
306 else
|
|
307 {
|
|
308 /* we use "command" or "cmd" to start the shell; slow but easy */
|
|
309 char_u *newcmd;
|
|
310
|
|
311 newcmd = lalloc(
|
|
312 STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE);
|
|
313 if (newcmd != NULL)
|
|
314 {
|
|
315 if (STRNICMP(cmd, "start ", 6) == 0)
|
|
316 {
|
|
317 sprintf((char *)newcmd, "%s\0", cmd+6);
|
|
318 if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31)
|
|
319 x = 0;
|
|
320 else
|
|
321 x = -1;
|
|
322 }
|
|
323 else
|
|
324 {
|
|
325 sprintf((char *)newcmd, "%s%s %s %s",
|
|
326 "",
|
|
327 p_sh,
|
|
328 p_shcf,
|
|
329 cmd);
|
|
330 x = mch_system((char *)newcmd, options);
|
|
331 }
|
|
332 vim_free(newcmd);
|
|
333 }
|
|
334 }
|
|
335
|
|
336 if (tmode == TMODE_RAW)
|
|
337 settmode(TMODE_RAW); /* set to raw mode */
|
|
338
|
|
339 if (x && !(options & SHELL_SILENT) && !emsg_silent)
|
|
340 {
|
|
341 smsg(_("shell returned %d"), x);
|
|
342 msg_putchar('\n');
|
|
343 }
|
|
344 #ifdef FEAT_TITLE
|
|
345 resettitle();
|
|
346 #endif
|
|
347
|
|
348 signal(SIGINT, SIG_DFL);
|
|
349 signal(SIGILL, SIG_DFL);
|
|
350 signal(SIGFPE, SIG_DFL);
|
|
351 signal(SIGSEGV, SIG_DFL);
|
|
352 signal(SIGTERM, SIG_DFL);
|
|
353 signal(SIGABRT, SIG_DFL);
|
|
354
|
|
355
|
|
356 return x;
|
|
357 }
|
|
358
|
|
359
|
|
360 /*
|
|
361 * Delay for half a second.
|
|
362 */
|
|
363 void
|
|
364 mch_delay(
|
|
365 long msec,
|
|
366 int ignoreinput)
|
|
367 {
|
|
368 #ifdef MUST_FIX
|
|
369 Sleep((int)msec); /* never wait for input */
|
|
370 #endif
|
|
371 }
|
|
372
|
|
373
|
|
374 /*
|
|
375 * check for an "interrupt signal": CTRL-break or CTRL-C
|
|
376 */
|
|
377 void
|
|
378 mch_breakcheck()
|
|
379 {
|
|
380 /* never used */
|
|
381 }
|
|
382
|
|
383
|
|
384 /*
|
|
385 * How much memory is available?
|
|
386 */
|
|
387 long_u
|
|
388 mch_avail_mem(
|
|
389 int special)
|
|
390 {
|
|
391 return GetFreeSpace(0);
|
|
392 }
|
|
393
|
|
394
|
|
395 /*
|
|
396 * Like rename(), returns 0 upon success, non-zero upon failure.
|
|
397 * Should probably set errno appropriately when errors occur.
|
|
398 */
|
|
399 int
|
|
400 mch_rename(
|
|
401 const char *pszOldFile,
|
|
402 const char *pszNewFile)
|
|
403 {
|
|
404
|
|
405 /*
|
|
406 * No need to play tricks, this isn't rubbish like Windows 95 <g>
|
|
407 */
|
|
408 return rename(pszOldFile, pszNewFile);
|
|
409
|
|
410 }
|
|
411
|
|
412 /*
|
|
413 * Get the default shell for the current hardware platform
|
|
414 */
|
|
415 char*
|
|
416 default_shell()
|
|
417 {
|
|
418 char* psz = NULL;
|
|
419
|
|
420 psz = "command.com";
|
|
421
|
|
422 return psz;
|
|
423 }
|