blob: 66ca198ed294fc37272541aaa82f21ed58b2abc0 [file] [log] [blame]
/* vi:set ts=8 sts=4 sw=4:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* os_win16.c
*
* Win16 (Windows 3.1x) system-dependent routines.
* Carved brutally from os_win32.c by Vince Negri <vn@aslnet.co.uk>
*/
#ifdef __BORLANDC__
# pragma warn -par
# pragma warn -ucp
# pragma warn -use
# pragma warn -aus
# pragma warn -obs
#endif
#include "vim.h"
#include <dos.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <limits.h>
#include <process.h>
#undef chdir
#include <direct.h>
#include <shellapi.h> /* required for FindExecutable() */
/* Record all output and all keyboard & mouse input */
/* #define MCH_WRITE_DUMP */
#ifdef MCH_WRITE_DUMP
FILE* fdDump = NULL;
#endif
/*
* When generating prototypes for Win32 on Unix, these lines make the syntax
* errors disappear. They do not need to be correct.
*/
#ifdef PROTO
typedef int HANDLE;
typedef int SMALL_RECT;
typedef int COORD;
typedef int SHORT;
typedef int WORD;
typedef int DWORD;
typedef int BOOL;
typedef int LPSTR;
typedef int LPTSTR;
typedef int KEY_EVENT_RECORD;
typedef int MOUSE_EVENT_RECORD;
# define WINAPI
typedef int CONSOLE_CURSOR_INFO;
typedef char * LPCSTR;
# define WINBASEAPI
typedef int INPUT_RECORD;
# define _cdecl
#endif
#ifdef __BORLANDC__
/* being a more ANSI compliant compiler, BorlandC doesn't define _stricoll:
* but it does in BC 5.02! */
# if __BORLANDC__ < 0x502
int _stricoll(char *a, char *b);
# endif
#endif
/* cproto doesn't create a prototype for main() */
int _cdecl
VimMain
__ARGS((int argc, char **argv));
static int (_cdecl *pmain)(int, char **);
#ifndef PROTO
void _cdecl SaveInst(HINSTANCE hInst);
static void (_cdecl *pSaveInst)(HINSTANCE);
int WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInst,
LPSTR lpszCmdLine,
int nCmdShow)
{
int argc;
char **argv;
char *tofree;
char prog[256];
/*
* Ron: added full path name so that the $VIM variable will get set to our
* startup path (so the .vimrc file can be found w/o a VIM env. var.)
* Remove the ".exe" extension, and find the 1st non-space.
*/
GetModuleFileName(hInstance, prog, 255);
if (*prog != NUL)
exe_name = FullName_save((char_u *)prog, FALSE);
/* Separate the command line into arguments. */
argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree);
if (argc == 0)
{
/* Error message? */
return 0;
}
pSaveInst = SaveInst;
pmain = VimMain;
pSaveInst(hInstance);
pmain(argc, argv);
free(argv);
if (tofree != NULL)
free(tofree);
return 0;
}
#endif
#ifdef FEAT_MOUSE
/*
* For the GUI the mouse handling is in gui_w32.c.
*/
void
mch_setmouse(
int on)
{
}
#endif /* FEAT_MOUSE */
/*
* GUI version of mch_init().
*/
void
mch_init()
{
extern int _fmode;
/* Let critical errors result in a failure, not in a dialog box. Required
* for the timestamp test to work on removed floppies. */
SetErrorMode(SEM_FAILCRITICALERRORS);
_fmode = O_BINARY; /* we do our own CR-LF translation */
/* Specify window size. Is there a place to get the default from? */
Rows = 25;
Columns = 80;
set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);
#ifdef FEAT_CLIPBOARD
clip_init(TRUE);
/*
* Vim's own clipboard format recognises whether the text is char, line,
* or rectangular block. Only useful for copying between two Vims.
* "VimClipboard" was used for previous versions, using the first
* character to specify MCHAR, MLINE or MBLOCK.
*/
clip_star.format = RegisterClipboardFormat("VimClipboard2");
clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
#endif
}
/*
* Do we have an interactive window?
*/
int
mch_check_win(
int argc,
char **argv)
{
return OK; /* GUI always has a tty */
}
/*
* return process ID
*/
long
mch_get_pid()
{
return (long)GetCurrentTask();
}
/*
* Specialised version of system().
* This version proceeds as follows:
* 1. Start the program with WinExec
* 2. Wait for the module use count of the program to go to 0
* (This is the best way of detecting the program has finished)
*/
static int
mch_system(char *cmd, int options)
{
DWORD ret = 0;
UINT wShowWindow;
UINT h_module;
MSG msg;
BOOL again = TRUE;
/*
* It's nicer to run a filter command in a minimized window, but in
*/
if (options & SHELL_DOOUT)
wShowWindow = SW_SHOWMINIMIZED;
else
wShowWindow = SW_SHOWNORMAL;
/* Now, run the command */
h_module = WinExec((LPCSTR)cmd, wShowWindow);
if (h_module < 32)
{
/*error*/
ret = -h_module;
}
else
{
/* Wait for the command to terminate before continuing */
while (GetModuleUsage((HINSTANCE)h_module) > 0 && again )
{
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) && again )
{
if(msg.message == WM_QUIT)
{
PostQuitMessage(msg.wParam);
again = FALSE;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return ret;
}
/*
* Either execute a command by calling the shell or start a new shell
*/
int
mch_call_shell(
char_u *cmd,
int options) /* SHELL_, see vim.h */
{
int x;
int tmode = cur_tmode;
out_flush();
#ifdef MCH_WRITE_DUMP
if (fdDump)
{
fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
fflush(fdDump);
}
#endif
/*
* Catch all deadly signals while running the external command, because a
* CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us.
*/
signal(SIGINT, SIG_IGN);
signal(SIGILL, SIG_IGN);
signal(SIGFPE, SIG_IGN);
signal(SIGSEGV, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGABRT, SIG_IGN);
if (options & SHELL_COOKED)
settmode(TMODE_COOK); /* set to normal mode */
if (cmd == NULL)
{
x = mch_system(p_sh, options);
}
else
{
/* we use "command" or "cmd" to start the shell; slow but easy */
char_u *newcmd;
newcmd = lalloc(
STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE);
if (newcmd != NULL)
{
if (STRNICMP(cmd, "start ", 6) == 0)
{
sprintf((char *)newcmd, "%s\0", cmd+6);
if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31)
x = 0;
else
x = -1;
}
else
{
sprintf((char *)newcmd, "%s%s %s %s",
"",
p_sh,
p_shcf,
cmd);
x = mch_system((char *)newcmd, options);
}
vim_free(newcmd);
}
}
if (tmode == TMODE_RAW)
settmode(TMODE_RAW); /* set to raw mode */
if (x && !(options & SHELL_SILENT) && !emsg_silent)
{
smsg(_("shell returned %d"), x);
msg_putchar('\n');
}
#ifdef FEAT_TITLE
resettitle();
#endif
signal(SIGINT, SIG_DFL);
signal(SIGILL, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGABRT, SIG_DFL);
return x;
}
/*
* Delay for half a second.
*/
void
mch_delay(
long msec,
int ignoreinput)
{
#ifdef MUST_FIX
Sleep((int)msec); /* never wait for input */
#endif
}
/*
* check for an "interrupt signal": CTRL-break or CTRL-C
*/
void
mch_breakcheck()
{
/* never used */
}
/*
* How much memory is available?
*/
long_u
mch_avail_mem(
int special)
{
return GetFreeSpace(0);
}
/*
* Like rename(), returns 0 upon success, non-zero upon failure.
* Should probably set errno appropriately when errors occur.
*/
int
mch_rename(
const char *pszOldFile,
const char *pszNewFile)
{
/*
* No need to play tricks, this isn't rubbish like Windows 95 <g>
*/
return rename(pszOldFile, pszNewFile);
}
/*
* Get the default shell for the current hardware platform
*/
char*
default_shell()
{
char* psz = NULL;
psz = "command.com";
return psz;
}