📄 os_win32.c
字号:
}
#ifdef USE_GUI_WIN32
#include <shellapi.h> /* required for FindExecutable() */
/*
* GUI version of mch_windinit().
*/
void
mch_windinit()
{
extern int _fmode;
PlatformId();
/* Specify window size. Is there a place to get the default from? */
Rows = 25;
Columns = 80;
_fmode = O_BINARY; /* we do our own CR-LF translation */
/* Look for 'vimrun' */
if (!gui_is_win32s())
{
char_u vimrun_location[2 * _MAX_PATH + 2];
char_u widename[40];
/* First try in same directory as gvim.exe */
STRCPY(vimrun_location, exe_name);
STRCPY(gettail(vimrun_location), "vimrun.exe");
if (mch_getperm(vimrun_location) >= 0)
{
STRCPY(gettail(vimrun_location), "vimrun ");
vimrun_path = (char *)vim_strsave(vimrun_location);
s_dont_use_vimrun = FALSE;
}
else
{
/* There appears to be a bug in FindExecutableA() on Windows NT.
* Use FindExecutableW() instead... */
if (g_PlatformId == VER_PLATFORM_WIN32_NT)
{
MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)"vimrun.exe", -1,
(LPWSTR)widename, 20);
if (FindExecutableW((LPCWSTR)widename, (LPCWSTR)"",
(LPWSTR)vimrun_location) > (HINSTANCE)32)
s_dont_use_vimrun = FALSE;
}
else
{
if (FindExecutableA((LPCTSTR)"vimrun.exe", (LPCTSTR)"",
(LPTSTR)vimrun_location) > (HINSTANCE)32)
s_dont_use_vimrun = FALSE;
}
}
if (s_dont_use_vimrun)
MessageBox(NULL,
"VIMRUN.EXE not found in your $PATH.\n"
"External commands will not pause after completion.\n"
"See :help win32-vimrun for more information.",
"Vim Warning",
MB_ICONWARNING);
}
#ifdef USE_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.
*/
clipboard.format = RegisterClipboardFormat("VimClipboard");
#endif
}
/*
* GUI version of mch_windexit().
* Shut down and exit with status `r'
* Careful: mch_windexit() may be called before mch_windinit()!
*/
void
mch_windexit(
int r)
{
mch_display_error();
ml_close_all(TRUE); /* remove all memfiles */
# ifdef HAVE_OLE
UninitOLE();
# endif
if (gui.in_use)
gui_exit(r);
exit(r);
}
#else /* USE_GUI_WIN32 */
static char g_szOrigTitle[256];
static int g_fWindInitCalled = FALSE;
static CONSOLE_CURSOR_INFO g_cci;
static DWORD g_cmodein = 0;
static DWORD g_cmodeout = 0;
/*
* Because of a bug in the Windows 95 Console, we need to set the screen size
* back when switching screens.
*/
static int g_nOldRows = 0;
static int g_nOldColumns = 0;
/*
* non-GUI version of mch_windinit().
*/
void
mch_windinit()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
extern int _fmode;
PlatformId();
_fmode = O_BINARY; /* we do our own CR-LF translation */
out_flush();
/* Obtain handles for the standard Console I/O devices */
if (read_cmd_fd == 0)
g_hConIn = GetStdHandle(STD_INPUT_HANDLE);
else
create_conin();
g_hSavOut = GetStdHandle(STD_OUTPUT_HANDLE);
g_hCurOut = g_hSavOut;
/* Get current text attributes */
GetConsoleScreenBufferInfo(g_hSavOut, &csbi);
g_attrCurrent = g_attrDefault = csbi.wAttributes;
GetConsoleCursorInfo(g_hSavOut, &g_cci);
/* set termcap codes to current text attributes */
update_tcap(csbi.wAttributes);
GetConsoleMode(g_hConIn, &g_cmodein);
GetConsoleMode(g_hSavOut, &g_cmodeout);
GetConsoleTitle(g_szOrigTitle, sizeof(g_szOrigTitle));
ui_get_winsize();
g_nOldRows = Rows;
g_nOldColumns = Columns;
#ifdef MCH_WRITE_DUMP
fdDump = fopen("dump", "wt");
if (fdDump)
{
time_t t;
time(&t);
fputs(ctime(&t), fdDump);
fflush(fdDump);
}
#endif
g_fWindInitCalled = TRUE;
#ifdef USE_MOUSE
g_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT);
#endif
#ifdef USE_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.
*/
clipboard.format = RegisterClipboardFormat("VimClipboard");
#endif
/* This will be NULL on anything but NT 4.0 */
s_pfnGetConsoleKeyboardLayoutName =
(PFNGCKLN) GetProcAddress(GetModuleHandle("kernel32.dll"),
"GetConsoleKeyboardLayoutNameA");
/*
* We don't really want to jump to our own screen yet; do that after
* starttermcap(). This flashes the window, sorry about that, but
* otherwise "vim -r" doesn't work.
*/
g_hCurOut = g_hSavOut;
SetConsoleActiveScreenBuffer(g_hCurOut);
}
/*
* non-GUI version of mch_windexit().
* Shut down and exit with status `r'
* Careful: mch_windexit() may be called before mch_windinit()!
*/
void
mch_windexit(
int r)
{
stoptermcap();
out_char('\r');
out_char('\n');
out_flush();
if (g_fWindInitCalled)
settmode(TMODE_COOK);
if (g_hConOut != INVALID_HANDLE_VALUE)
{
(void)CloseHandle(g_hConOut);
if (g_hSavOut != INVALID_HANDLE_VALUE)
{
SetConsoleTextAttribute(g_hSavOut, g_attrDefault);
SetConsoleCursorInfo(g_hSavOut, &g_cci);
}
}
ml_close_all(TRUE); /* remove all memfiles */
if (g_fWindInitCalled)
{
mch_restore_title(3);
#ifdef MCH_WRITE_DUMP
if (fdDump)
{
time_t t;
time(&t);
fputs(ctime(&t), fdDump);
fclose(fdDump);
}
fdDump = NULL;
#endif
}
exit(r);
}
#endif /* USE_GUI_WIN32 */
/*
* Do we have an interactive window?
*/
int
mch_check_win(
int argc,
char **argv)
{
char temp[256];
int i;
/* store the name of the executable, may be used for $VIM */
GetModuleFileName(NULL, temp, 255);
if (*temp != NUL)
exe_name = FullName_save((char_u *)temp, FALSE);
/* Init the tables for toupper() and tolower() */
for (i = 0; i < 256; ++i)
toupper_tab[i] = tolower_tab[i] = i;
CharUpperBuff(toupper_tab, 256);
CharLowerBuff(tolower_tab, 256);
#ifdef USE_GUI_WIN32
return OK; /* GUI always has a tty */
#else
if (isatty(1))
return OK;
return FAIL;
#endif
}
/*
* Return TRUE if the input comes from a terminal, FALSE otherwise.
*/
int
mch_input_isatty()
{
#ifdef USE_GUI_WIN32
return OK; /* GUI always has a tty */
#else
if (isatty(read_cmd_fd))
return TRUE;
return FALSE;
#endif
}
/*
* Turn a file name into its canonical form. Replace slashes with backslashes.
* This used to replace backslashes with slashes, but that caused problems
* when using the file name as a command. We can't have a mix of slashes and
* backslashes, because comparing file names will not work correctly. The
* commands that use file names should be prepared to handle the backslashes.
*/
static void
canonicalize_filename(
char *pszName)
{
if (pszName == NULL)
return;
for ( ; *pszName; pszName++)
{
if (*pszName == '/')
*pszName = '\\';
}
}
/*
* fname_case(): Set the case of the file name, if it already exists.
*/
void
fname_case(
char_u *name)
{
char szTrueName[_MAX_PATH + 2];
char *psz, *pszPrev;
const int len = (name != NULL) ? STRLEN(name) : 0;
if (len == 0)
return;
STRNCPY(szTrueName, name, _MAX_PATH);
szTrueName[_MAX_PATH] = '\0'; /* ensure it's sealed off! */
STRCAT(szTrueName, "\\"); /* sentinel */
for (psz = szTrueName; *psz != NUL; psz++)
if (*psz == '/')
*psz = '\\';
psz = pszPrev = szTrueName;
/* Skip leading \\ in UNC name or drive letter */
if (len > 2 && ((psz[0] == '\\' && psz[1] == '\\')
|| (isalpha(psz[0]) && psz[1] == ':')))
{
psz = pszPrev = szTrueName + 2;
}
while (*psz != NUL)
{
WIN32_FIND_DATA fb;
HANDLE hFind;
while (*psz != '\\')
psz++;
*psz = NUL;
if ((hFind = FindFirstFile(szTrueName, &fb)) != INVALID_HANDLE_VALUE)
{
/* avoid ".." and ".", etc */
if (_stricoll(pszPrev, fb.cFileName) == 0)
STRCPY(pszPrev, fb.cFileName);
FindClose(hFind);
}
*psz++ = '\\';
pszPrev = psz;
}
*--psz = NUL; /* remove sentinel */
STRCPY(name, szTrueName);
}
/*
* mch_settitle(): set titlebar of our window
* Can the icon also be set?
*/
void
mch_settitle(
char_u *title,
char_u *icon)
{
#ifdef USE_GUI_WIN32
gui_mch_settitle(title, icon);
#else
if (title != NULL)
SetConsoleTitle(title);
#endif
}
/*
* Restore the window/icon title.
* which is one of:
* 1: Just restore title
* 2: Just restore icon (which we don't have)
* 3: Restore title and icon (which we don't have)
*/
void
mch_restore_title(
int which)
{
#ifndef USE_GUI_WIN32
mch_settitle((which & 1) ? g_szOrigTitle : NULL, NULL);
#endif
}
/*
* Return TRUE if we can restore the title (we can)
*/
int
mch_can_restore_title()
{
return TRUE;
}
/*
* Return TRUE if we can restore the icon (we can't)
*/
int
mch_can_restore_icon()
{
return FALSE;
}
/*
* Insert user name in s[len].
*/
int
mch_get_user_name(
char_u *s,
int len)
{
char szUserName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD cch = sizeof szUserName;
if (GetUserName(szUserName, &cch))
{
STRNCPY(s, szUserName, len);
return OK;
}
s[0] = NUL;
return FAIL;
}
/*
* Insert host name in s[len].
*/
void
mch_get_host_name(
char_u *s,
int len)
{
char szHostName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD cch = sizeof szHostName;
if (GetComputerName(szHostName, &cch))
{
STRCPY(s, "PC ");
STRNCPY(s + 3, szHostName, len - 3);
}
else
STRNCPY(s, "PC (Win32 Vim)", len);
}
/*
* return process ID
*/
long
mch_get_pid()
{
return (long)GetCurrentProcessId();
}
/*
* Get name of current directory into buffer 'buf' of length 'len' bytes.
* Return OK for success, FAIL for failure.
*/
int
mch_dirname(
char_u *buf,
int len)
{
/*
* Originally this was:
* return (getcwd(buf, len) != NULL ? OK : FAIL);
* But the Win32s known bug list says that getcwd() doesn't work
* so use the Win32 system call instead. <Negri>
*/
return (GetCurrentDirectory(len,buf) != 0 ? OK : FAIL);
}
/*
* Get absolute file name into buffer 'buf' of length 'len' bytes,
* turning all '/'s into '\\'s and getting the correct case of each
* component of the file name. Return OK or FAIL.
*/
int
mch_FullName(
char_u *fname,
char_u *buf,
int len,
int force)
{
int nResult = FAIL;
if (fname == NULL) /* always fail */
return FAIL;
if (_fullpath(buf, fname, len - 1) == NULL)
STRNCPY(buf, fname, len); /* failed, use the relative path name */
else
{
if (mch_isdir(fname))
STRCAT(buf, "\\");
nResult = OK;
}
fname_case(buf);
return nResult;
}
/*
* return TRUE if `fname' is an absolute path name
*/
int
mch_isFullName(
char_u *fname)
{
char szName[_MAX_PATH+1];
mch_FullName(fname, szName, _MAX_PATH, FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -