📄 os_win32.c
字号:
return strcoll(fname, szName) == 0;
}
/*
* Replace all slashes by backslashes.
* This used to be the other way around, but MS-DOS sometimes has problems
* with slashes (e.g. in a command name). We can't have mixed slashes and
* backslashes, because comparing file names will not work correctly. The
* commands that use a file name should try to avoid the need to type a
* backslash twice.
*/
void
slash_adjust(p)
char_u *p;
{
while (*p)
{
if (*p == '/')
*p = '\\';
++p;
}
}
/*
* get file permissions for `name'
* -1 : error
* else FILE_ATTRIBUTE_* defined in winnt.h
*/
long
mch_getperm(
char_u *name)
{
return (long)GetFileAttributes((char *)name);
}
/*
* set file permission for `name' to `perm'
*/
int
mch_setperm(
char_u *name,
long perm)
{
perm |= FILE_ATTRIBUTE_ARCHIVE; /* file has changed, set archive bit */
return SetFileAttributes((char *)name, perm) ? OK : FAIL;
}
/*
* Set hidden flag for "name".
*/
void
mch_hide(char_u *name)
{
int perm;
perm = GetFileAttributes((char *)name);
if (perm >= 0)
{
perm |= FILE_ATTRIBUTE_HIDDEN;
SetFileAttributes((char *)name, perm);
}
}
/*
* return TRUE if "name" is a directory
* return FALSE if "name" is not a directory or upon error
*/
int
mch_isdir(char_u *name)
{
int f = mch_getperm(name);
if (f == -1)
return FALSE; /* file does not exist at all */
return (f & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
#ifdef USE_GUI_WIN32
void
mch_settmode(int tmode)
{
/* nothing to do */
}
int
mch_get_winsize()
{
/* never used */
return OK;
}
void
mch_set_winsize()
{
/* never used */
}
#else
/*
* handler for ctrl-break, ctrl-c interrupts, and fatal events.
*/
static BOOL WINAPI
handler_routine(
DWORD dwCtrlType)
{
switch (dwCtrlType)
{
case CTRL_C_EVENT:
g_fCtrlCPressed = TRUE;
return TRUE;
case CTRL_BREAK_EVENT:
g_fCBrkPressed = TRUE;
return TRUE;
/* fatal events: shut down gracefully */
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
windgoto((int)Rows - 1, 0);
sprintf((char *)IObuff, "Vim: Caught %s event\n",
(dwCtrlType == CTRL_CLOSE_EVENT ? "close"
: dwCtrlType == CTRL_LOGOFF_EVENT ? "logoff" : "shutdown"));
#ifdef DEBUG
OutputDebugString(IObuff);
#endif
preserve_exit(); /* output IObuff, preserve files and exit */
return TRUE; /* not reached */
default:
return FALSE;
}
}
/*
* set the tty in (raw) ? "raw" : "cooked" mode
*/
void
mch_settmode(
int tmode)
{
DWORD cmodein;
DWORD cmodeout;
GetConsoleMode(g_hConIn, &cmodein);
GetConsoleMode(g_hCurOut, &cmodeout);
if (tmode == TMODE_RAW)
{
cmodein &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT |
ENABLE_ECHO_INPUT);
cmodein |= (
#ifdef USE_MOUSE
(g_fMouseActive ? ENABLE_MOUSE_INPUT : 0) |
#endif
ENABLE_WINDOW_INPUT);
SetConsoleMode(g_hConIn, cmodein);
cmodeout &= ~(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
SetConsoleMode(g_hCurOut, cmodeout);
SetConsoleCtrlHandler(handler_routine, TRUE);
}
else /* cooked */
{
cmodein = g_cmodein;
cmodeout = g_cmodeout;
SetConsoleMode(g_hConIn, g_cmodein);
SetConsoleMode(g_hCurOut, g_cmodeout);
SetConsoleCtrlHandler(handler_routine, FALSE);
}
#ifdef MCH_WRITE_DUMP
if (fdDump)
{
fprintf(fdDump, "mch_settmode(%s, CurOut = %s, in = %x, out = %x)\n",
tmode == TMODE_RAW ? "raw" :
tmode == TMODE_COOK ? "cooked" : "normal",
(g_hCurOut == g_hSavOut ? "Sav" : "Con"),
cmodein, cmodeout);
fflush(fdDump);
}
#endif
}
/*
* Get the size of the current window in `Rows' and `Columns'
* Return OK when size could be determined, FAIL otherwise.
*/
int
mch_get_winsize()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(g_hCurOut, &csbi))
{
Rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
Columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
}
else
{
Rows = 25;
Columns = 80;
}
if (Columns < MIN_COLUMNS || Rows < MIN_LINES)
{
/* these values are overwritten by termcap size or default */
Rows = 25;
Columns = 80;
}
check_winsize();
set_scroll_region(0, 0, Columns - 1, Rows - 1);
return OK;
}
/*
* Set a console window to `xSize' * `ySize'
*/
static void
ResizeConBufAndWindow(
HANDLE hConsole,
int xSize,
int ySize)
{
CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
SMALL_RECT srWindowRect; /* hold the new console size */
COORD coordScreen;
int did_start_termcap = FALSE;
#ifdef MCH_WRITE_DUMP
if (fdDump)
{
fprintf(fdDump, "ResizeConBufAndWindow(%d, %d)\n", xSize, ySize);
fflush(fdDump);
}
#endif
/*
* The resizing MUST be done while in our own console buffer, otherwise it
* will never be possible to restore the old one, and we will crash on
* exit in Windows 95.
*/
if (g_hCurOut != g_hConOut)
{
termcap_mode_start();
did_start_termcap = TRUE;
}
/* get the largest size we can size the console window to */
coordScreen = GetLargestConsoleWindowSize(hConsole);
/* define the new console window size and scroll position */
srWindowRect.Left = srWindowRect.Top = (SHORT) 0;
srWindowRect.Right = (SHORT) (min(xSize, coordScreen.X) - 1);
srWindowRect.Bottom = (SHORT) (min(ySize, coordScreen.Y) - 1);
if (GetConsoleScreenBufferInfo(g_hCurOut, &csbi))
{
int sx, sy;
sx = csbi.srWindow.Right - csbi.srWindow.Left + 1;
sy = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
if (sy < ySize || sx < xSize)
{
/*
* Increasing number of lines/columns, do buffer first.
* Use the maximal size in x and y direction.
*/
if (sy < ySize)
coordScreen.Y = ySize;
else
coordScreen.Y = sy;
if (sx < xSize)
coordScreen.X = xSize;
else
coordScreen.X = sx;
SetConsoleScreenBufferSize(hConsole, coordScreen);
}
}
if (!SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect))
{
#ifdef MCH_WRITE_DUMP
if (fdDump)
{
fprintf(fdDump, "SetConsoleWindowInfo failed: %lx\n",
GetLastError());
fflush(fdDump);
}
#endif
}
/* define the new console buffer size */
coordScreen.X = xSize;
coordScreen.Y = ySize;
if (!SetConsoleScreenBufferSize(hConsole, coordScreen))
{
#ifdef MCH_WRITE_DUMP
if (fdDump)
{
fprintf(fdDump, "SetConsoleScreenBufferSize failed: %lx\n",
GetLastError());
fflush(fdDump);
}
#endif
}
if (did_start_termcap)
termcap_mode_end();
}
/*
* Set the console window to `Rows' * `Columns'
*/
void
mch_set_winsize()
{
COORD coordScreen;
/* Don't change window size while still starting up */
if (suppress_winsize)
{
suppress_winsize = 2;
return;
}
coordScreen = GetLargestConsoleWindowSize(g_hCurOut);
/* Clamp Rows and Columns to reasonable values */
if (Rows > coordScreen.Y)
Rows = coordScreen.Y;
if (Columns > coordScreen.X)
Columns = coordScreen.X;
ResizeConBufAndWindow(g_hCurOut, Columns, Rows);
set_scroll_region(0, 0, Columns - 1, Rows - 1);
}
/*
* Called when started up, to set the winsize that was delayed.
*/
void
mch_set_winsize_now()
{
if (suppress_winsize == 2)
{
suppress_winsize = 0;
mch_set_winsize();
check_winsize(); /* in case 'columns' changed */
}
suppress_winsize = 0;
}
#endif /* USE_GUI_WIN32 */
/*
* We have no job control, so fake it by starting a new shell.
*/
void
mch_suspend()
{
suspend_shell();
}
#if defined(USE_GUI_WIN32) || defined(PROTO)
#ifdef OLD_CONSOLE_STUFF
/*
* Functions to open and close a console window.
* The open function sets the size of the window to 25x80, to avoid problems
* with Windows 95. In the long term should make sure that the "close" icon
* cannot crash vim (it doesn't do so at the moment!).
* The close function waits for the user to press a key before closing the
* window.
*/
static BOOL
ConsoleCtrlHandler(DWORD what)
{
return TRUE;
}
static void
mch_open_console(void)
{
COORD size;
SMALL_RECT window_size;
HANDLE console_handle;
AllocConsole();
/* On windows 95, we must use a 25x80 console size, to avoid trouble with
* some DOS commands */
if (g_PlatformId != VER_PLATFORM_WIN32_NT)
{
console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
size.X = 80;
size.Y = 25;
window_size.Left = 0;
window_size.Top = 0;
window_size.Right = 79;
window_size.Bottom = 24;
/* First set the window size, then also resize the screen buffer, to
* avoid a scrollbar */
SetConsoleWindowInfo(console_handle, TRUE, &window_size);
SetConsoleScreenBufferSize(console_handle, size);
}
SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleCtrlHandler, TRUE);
}
static void
mch_close_console(int wait_key, DWORD ret)
{
if (wait_key)
{
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
DWORD number;
static char message[] = "\nPress any key to close this window...";
static char err_buf[80];
char buffer[1];
if (ret)
{
sprintf(err_buf, "\n%ld returned.", ret);
WriteConsole(hStderr, err_buf, strlen(err_buf), &number, NULL);
}
/* Write a message to the user */
WriteConsole(hStderr, message, sizeof(message)-1, &number, NULL);
/* Clear the console input buffer, and set the input to "raw" mode */
FlushConsoleInputBuffer(hStdin);
SetConsoleMode(hStdin, 0);
/* Wait for a keypress */
ReadConsole(hStdin, buffer, 1, &number, NULL);
}
/* Close the console window */
FreeConsole();
}
#endif
#ifdef mch_errmsg
# undef mch_errmsg
# undef mch_display_error
#endif
/*
* Record an error message for later display.
*/
void
mch_errmsg(char *str)
{
int len = STRLEN(str) + 1;
if (error_ga.ga_growsize == 0)
{
error_ga.ga_growsize = 80;
error_ga.ga_itemsize = 1;
}
if (ga_grow(&error_ga, len) == OK)
{
mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
(char_u *)str, len);
--len; /* don't count the NUL at the end */
error_ga.ga_len += len;
error_ga.ga_room -= len;
}
}
/*
* Display the saved error message(s).
*/
void
mch_display_error()
{
char *p;
if (error_ga.ga_data != NULL)
{
/* avoid putting up a message box with blanks only */
for (p = (char *)error_ga.ga_data; *p; ++p)
if (!isspace(*p))
{
MessageBox(0, p, "Vim", MB_TASKMODAL|MB_SETFOREGROUND);
break;
}
ga_clear(&error_ga);
}
}
/*
* Specialised version of system() for Win32 GUI mode.
* This version proceeds as follows:
* 1. Create a console window for use by the subprocess
* 2. Run the subprocess (it gets the allocated console by default)
* 3. Wait for the subprocess to terminate and get its exit code
* 4. Prompt the user to press a key to close the console window
*/
static BOOL fUseConsole = TRUE;
static int
mch_system(char *cmd, int options)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD ret = 0;
si.cb = sizeof(si);
si.lpReserved = NULL;
si.lpDesktop = NULL;
si.lpTitle = NULL;
si.dwFlags = STARTF_USESHOWWINDOW;
/*
* It's nicer to run a filter command in a minimized window, but in
* Windows 95 this makes the command MUCH slower.
*/
if ((options & SHELL_DOOUT) && !mch_windows95())
si.wShowWindow = SW_SHOWMINIMIZED;
else
si.wShowWindow = SW_SHOWNORMAL;
si.cbReserved2 = 0;
si.lpReserved2 = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -