blob: b620149e792be460a8b6428f0aa4922a89686788 [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 *
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
Bram Moolenaar071d4272004-06-13 20:20:40 +000023#include "vim.h"
24
Bram Moolenaar071d4272004-06-13 20:20:40 +000025#include <dos.h>
26#include <string.h>
27#include <sys/types.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000028#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
41FILE* 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
50typedef int HANDLE;
51typedef int SMALL_RECT;
52typedef int COORD;
53typedef int SHORT;
54typedef int WORD;
55typedef int DWORD;
56typedef int BOOL;
57typedef int LPSTR;
58typedef int LPTSTR;
59typedef int KEY_EVENT_RECORD;
60typedef int MOUSE_EVENT_RECORD;
61# define WINAPI
62typedef int CONSOLE_CURSOR_INFO;
63typedef char * LPCSTR;
64# define WINBASEAPI
65typedef 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
73int _stricoll(char *a, char *b);
74# endif
75#endif
76
77/* cproto doesn't create a prototype for main() */
78int _cdecl
79VimMain
80__ARGS((int argc, char **argv));
Bram Moolenaar7fae6362005-06-30 22:06:41 +000081static int (_cdecl *pmain)(int, char **);
Bram Moolenaar071d4272004-06-13 20:20:40 +000082
83#ifndef PROTO
84void _cdecl SaveInst(HINSTANCE hInst);
Bram Moolenaar7fae6362005-06-30 22:06:41 +000085static void (_cdecl *pSaveInst)(HINSTANCE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000086
87int WINAPI
88WinMain(
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);
Bram Moolenaar12806c82008-11-12 12:36:30 +0000122 if (tofree != NULL)
123 free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000124
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
140mch_setmouse(
141 int on)
142{
143}
144#endif /* FEAT_MOUSE */
145
146
147
148/*
149 * GUI version of mch_init().
150 */
151 void
152mch_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
190mch_check_win(
191 int argc,
192 char **argv)
193{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194 return OK; /* GUI always has a tty */
195}
196
197
198/*
199 * return process ID
200 */
201 long
202mch_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
217mch_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 {
Bram Moolenaar62dbdc42011-10-20 18:24:22 +0200246 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && again)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247 {
Bram Moolenaar62dbdc42011-10-20 18:24:22 +0200248 if (msg.message == WM_QUIT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249
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
267mch_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
361mch_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
375mch_breakcheck()
376{
377 /* never used */
378}
379
380
381/*
Bram Moolenaar11b73d62012-06-29 15:51:30 +0200382 * How much memory is available in Kbyte?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 */
384 long_u
385mch_avail_mem(
386 int special)
387{
Bram Moolenaar11b73d62012-06-29 15:51:30 +0200388 return GetFreeSpace(0) >> 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389}
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
397mch_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*
413default_shell()
414{
415 char* psz = NULL;
416
417 psz = "command.com";
418
419 return psz;
420}