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