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 "vimio.h" 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 43FILE* 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 52typedef int HANDLE; 53typedef int SMALL_RECT; 54typedef int COORD; 55typedef int SHORT; 56typedef int WORD; 57typedef int DWORD; 58typedef int BOOL; 59typedef int LPSTR; 60typedef int LPTSTR; 61typedef int KEY_EVENT_RECORD; 62typedef int MOUSE_EVENT_RECORD; 63# define WINAPI 64typedef int CONSOLE_CURSOR_INFO; 65typedef char * LPCSTR; 66# define WINBASEAPI 67typedef 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 75int _stricoll(char *a, char *b); 76# endif 77#endif 78 79/* cproto doesn't create a prototype for main() */ 80int _cdecl 81VimMain 82__ARGS((int argc, char **argv)); 83static int (_cdecl *pmain)(int, char **); 84 85#ifndef PROTO 86void _cdecl SaveInst(HINSTANCE hInst); 87static void (_cdecl *pSaveInst)(HINSTANCE); 88 89int WINAPI 90WinMain( 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 if (tofree != NULL) 125 free(tofree); 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 142mch_setmouse( 143 int on) 144{ 145} 146#endif /* FEAT_MOUSE */ 147 148 149 150/* 151 * GUI version of mch_init(). 152 */ 153 void 154mch_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 192mch_check_win( 193 int argc, 194 char **argv) 195{ 196 return OK; /* GUI always has a tty */ 197} 198 199 200/* 201 * return process ID 202 */ 203 long 204mch_get_pid() 205{ 206 return (long)GetCurrentTask(); 207} 208 209 210/* 211 * Specialised version of system(). 212 * This version proceeds as follows: 213 * 1. Start the program with WinExec 214 * 2. Wait for the module use count of the program to go to 0 215 * (This is the best way of detecting the program has finished) 216 */ 217 218 static int 219mch_system(char *cmd, int options) 220{ 221 DWORD ret = 0; 222 UINT wShowWindow; 223 UINT h_module; 224 MSG msg; 225 BOOL again = TRUE; 226 227 /* 228 * It's nicer to run a filter command in a minimized window, but in 229 */ 230 if (options & SHELL_DOOUT) 231 wShowWindow = SW_SHOWMINIMIZED; 232 else 233 wShowWindow = SW_SHOWNORMAL; 234 235 /* Now, run the command */ 236 h_module = WinExec((LPCSTR)cmd, wShowWindow); 237 238 if (h_module < 32) 239 { 240 /*error*/ 241 ret = -h_module; 242 } 243 else 244 { 245 /* Wait for the command to terminate before continuing */ 246 while (GetModuleUsage((HINSTANCE)h_module) > 0 && again ) 247 { 248 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) && again ) 249 { 250 if(msg.message == WM_QUIT) 251 252 { 253 PostQuitMessage(msg.wParam); 254 again = FALSE; 255 } 256 TranslateMessage(&msg); 257 DispatchMessage(&msg); 258 } 259 } 260 } 261 262 return ret; 263} 264 265/* 266 * Either execute a command by calling the shell or start a new shell 267 */ 268 int 269mch_call_shell( 270 char_u *cmd, 271 int options) /* SHELL_, see vim.h */ 272{ 273 int x; 274 int tmode = cur_tmode; 275 276 out_flush(); 277 278 279#ifdef MCH_WRITE_DUMP 280 if (fdDump) 281 { 282 fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options); 283 fflush(fdDump); 284 } 285#endif 286 287 /* 288 * Catch all deadly signals while running the external command, because a 289 * CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us. 290 */ 291 signal(SIGINT, SIG_IGN); 292 signal(SIGILL, SIG_IGN); 293 signal(SIGFPE, SIG_IGN); 294 signal(SIGSEGV, SIG_IGN); 295 signal(SIGTERM, SIG_IGN); 296 signal(SIGABRT, SIG_IGN); 297 298 if (options & SHELL_COOKED) 299 settmode(TMODE_COOK); /* set to normal mode */ 300 301 if (cmd == NULL) 302 { 303 x = mch_system(p_sh, options); 304 } 305 else 306 { 307 /* we use "command" or "cmd" to start the shell; slow but easy */ 308 char_u *newcmd; 309 310 newcmd = lalloc( 311 STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE); 312 if (newcmd != NULL) 313 { 314 if (STRNICMP(cmd, "start ", 6) == 0) 315 { 316 sprintf((char *)newcmd, "%s\0", cmd+6); 317 if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31) 318 x = 0; 319 else 320 x = -1; 321 } 322 else 323 { 324 sprintf((char *)newcmd, "%s%s %s %s", 325 "", 326 p_sh, 327 p_shcf, 328 cmd); 329 x = mch_system((char *)newcmd, options); 330 } 331 vim_free(newcmd); 332 } 333 } 334 335 if (tmode == TMODE_RAW) 336 settmode(TMODE_RAW); /* set to raw mode */ 337 338 if (x && !(options & SHELL_SILENT) && !emsg_silent) 339 { 340 smsg(_("shell returned %d"), x); 341 msg_putchar('\n'); 342 } 343#ifdef FEAT_TITLE 344 resettitle(); 345#endif 346 347 signal(SIGINT, SIG_DFL); 348 signal(SIGILL, SIG_DFL); 349 signal(SIGFPE, SIG_DFL); 350 signal(SIGSEGV, SIG_DFL); 351 signal(SIGTERM, SIG_DFL); 352 signal(SIGABRT, SIG_DFL); 353 354 355 return x; 356} 357 358 359/* 360 * Delay for half a second. 361 */ 362 void 363mch_delay( 364 long msec, 365 int ignoreinput) 366{ 367#ifdef MUST_FIX 368 Sleep((int)msec); /* never wait for input */ 369#endif 370} 371 372 373/* 374 * check for an "interrupt signal": CTRL-break or CTRL-C 375 */ 376 void 377mch_breakcheck() 378{ 379 /* never used */ 380} 381 382 383/* 384 * How much memory is available? 385 */ 386 long_u 387mch_avail_mem( 388 int special) 389{ 390 return GetFreeSpace(0); 391} 392 393 394/* 395 * Like rename(), returns 0 upon success, non-zero upon failure. 396 * Should probably set errno appropriately when errors occur. 397 */ 398 int 399mch_rename( 400 const char *pszOldFile, 401 const char *pszNewFile) 402{ 403 404 /* 405 * No need to play tricks, this isn't rubbish like Windows 95 <g> 406 */ 407 return rename(pszOldFile, pszNewFile); 408 409} 410 411/* 412 * Get the default shell for the current hardware platform 413 */ 414 char* 415default_shell() 416{ 417 char* psz = NULL; 418 419 psz = "command.com"; 420 421 return psz; 422} 423