📄 os_msdos.c
字号:
}
else
#endif
while (*p)
{
if (*p == '/')
*p = '\\';
++p;
}
}
/*
* return TRUE is fname is an absolute path name
*/
int
mch_isFullName(char_u *fname)
{
return (vim_strchr(fname, ':') != NULL);
}
/*
* get file permissions for 'name'
* -1 : error
* else FA_attributes defined in dos.h
*/
long
mch_getperm(char_u *name)
{
return (long)_chmod((char *)name, 0, 0); /* get file mode */
}
/*
* set file permission for 'name' to 'perm'
*
* return FAIL for failure, OK otherwise
*/
int
mch_setperm(
char_u *name,
long perm)
{
perm |= FA_ARCH; /* file has changed, set archive bit */
return (_chmod((char *)name, 1, (int)perm) == -1 ? FAIL : OK);
}
/*
* Set hidden flag for "name".
*/
void
mch_hide(char_u *name)
{
/* DOS 6.2 share.exe causes "seek error on file write" errors when making
* the swap file hidden. Thus don't do it. */
}
/*
* return TRUE if "name" is a directory
* return FALSE if "name" is not a directory
* return FALSE for error
*
* beware of a trailing backslash
*/
int
mch_isdir(char_u *name)
{
int f;
char_u *p;
p = name + strlen((char *)name);
if (p > name)
--p;
if (*p == '\\') /* remove trailing backslash for a moment */
*p = NUL;
else
p = NULL;
f = _chmod((char *)name, 0, 0);
if (p != NULL)
*p = '\\'; /* put back backslash */
if (f == -1)
return FALSE; /* file does not exist at all */
if ((f & FA_DIREC) == 0)
return FALSE; /* not a directory */
return TRUE;
}
/*
* Careful: mch_windexit() may be called before mch_windinit()!
*/
void
mch_windexit(int r)
{
settmode(TMODE_COOK);
stoptermcap();
set_interrupts(FALSE); /* restore interrupts */
out_char('\r');
out_char('\n');
out_flush();
ml_close_all(TRUE); /* remove all memfiles */
mch_restore_cursor_shape(TRUE);
exit(r);
}
/*
* set the tty in (raw) ? "raw" : "cooked" mode
* Does not change the tty, as bioskey() and kbhit() work raw all the time.
*/
void
mch_settmode(int tmode)
{
}
#ifdef USE_MOUSE
void
mch_setmouse(int on)
{
mouse_active = on;
mouse_hidden = TRUE; /* dont show it until moved */
}
#endif
/*
* set screen mode
* return FAIL for failure, OK otherwise
*/
int
mch_screenmode(char_u *arg)
{
int mode;
int i;
static char *(names[]) = {"BW40", "C40", "BW80", "C80", "MONO", "C4350"};
static int modes[] = { BW40, C40, BW80, C80, MONO, C4350};
mode = -1;
if (isdigit(*arg)) /* mode number given */
mode = atoi((char *)arg);
else
{
for (i = 0; i < sizeof(names) / sizeof(char_u *); ++i)
if (stricmp(names[i], (char *)arg) == 0)
{
mode = modes[i];
break;
}
}
if (mode == -1)
{
EMSG("Unsupported screen mode");
return FAIL;
}
textmode(mode); /* use Borland function */
#ifdef DJGPP
/* base address may have changed */
get_screenbase();
#endif
/* Screen colors may have changed. */
out_str(T_ME);
#ifdef USE_MOUSE
if (mode <= 1 || mode == 4 || mode == 5 || mode == 13 || mode == 0x13)
mouse_x_div = 16;
else
mouse_x_div = 8;
if (mode == 0x11 || mode == 0x12)
mouse_y_div = 16;
else if (mode == 0x10)
mouse_y_div = 14;
else
mouse_y_div = 8;
ui_get_winsize(); /* Rows is used in mouse_area() */
mouse_area(); /* set area where mouse can go */
#endif
return OK;
}
/*
* Structure used by Turbo-C/Borland-C to store video parameters.
*/
#ifndef DJGPP
extern struct text_info _video;
#endif
/*
* try to get the real window size
* return FAIL for failure, OK otherwise
*/
int
mch_get_winsize(void)
{
struct text_info textinfo;
/*
* The screenwidth is returned by the BIOS OK.
* The screenheight is in a location in the bios RAM, if the display is EGA or
* VGA.
*/
if (!term_console)
return FAIL;
gettextinfo(&textinfo);
Columns = textinfo.screenwidth;
Rows = textinfo.screenheight;
#ifndef DJGPP
if (textinfo.currmode > 10)
Rows = *(char far *)MK_FP(0x40, 0x84) + 1;
#endif
/*
* don't call set_window() when not doing full screen, since it will move
* the cursor. Also skip this when exiting.
*/
if (full_screen && !exiting)
set_window();
if (Columns < MIN_COLUMNS || Rows < MIN_LINES)
{
/* these values are overwritten by termcap size or default */
Columns = 80;
Rows = 25;
return FAIL;
}
check_winsize();
#ifdef DJGPP
mytextinit(&textinfo); /* Added by JML, 1/15/98 */
#endif
return OK;
}
/*
* Set the active window for delline/insline.
*/
void
set_window(void)
{
#ifndef DJGPP
_video.screenheight = Rows;
#endif
mywindow(1, 1, Columns, Rows);
screen_start();
}
void
mch_set_winsize(void)
{
/* should try to set the window size to Rows and Columns */
/* may involve switching display mode.... */
#ifdef USE_MOUSE
mouse_area(); /* set area where mouse can go */
#endif
}
/*
* call shell, return FAIL for failure, OK otherwise
* options == SHELL_FILTER if called by do_filter()
* options == SHELL_COOKED if term needs cooked mode
*/
int
mch_call_shell(
char_u *cmd,
int options)
{
int x;
char_u *newcmd;
out_flush();
if (options & SHELL_COOKED)
settmode(TMODE_COOK); /* set to normal mode */
set_interrupts(FALSE); /* restore interrupts */
#ifdef DJGPP
/* ignore signals while external command is running */
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
#endif
if (cmd == NULL)
x = system((char *)p_sh);
else
{
#ifdef DJGPP
/*
* Use 'shell' for system().
*/
setenv("SHELL", (char *)p_sh, 1);
x = system(cmd);
#else
/* we use "command" to start the shell, slow but easy */
newcmd = alloc(STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 3);
if (newcmd == NULL)
x = -1;
else
{
sprintf((char *)newcmd, "%s %s %s", p_sh, p_shcf, cmd);
x = system((char *)newcmd);
vim_free(newcmd);
}
#endif
}
#ifdef DJGPP
signal(SIGINT, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
#endif
settmode(TMODE_RAW); /* set to raw mode */
set_interrupts(TRUE); /* catch interrupts */
if (x && !expand_interactively)
{
msg_putchar('\n');
msg_outnum((long)x);
MSG_PUTS(" returned\n");
}
/* resettitle(); we don't have titles */
(void)ui_get_winsize(); /* display mode may have been changed */
return x;
}
/*
* check for an "interrupt signal": CTRL-break or CTRL-C
*/
void
mch_breakcheck(void)
{
if (ctrlc_pressed)
{
ctrlc_pressed = FALSE;
got_int = TRUE;
}
}
static int _cdecl pstrcmp(); /* BCC does not like the types */
static int _cdecl
pstrcmp(a, b)
char_u **a, **b;
{
return (stricmp((char *)*a, (char *)*b));
}
int
mch_has_wildcard(char_u *s)
{
return (vim_strpbrk(s, (char_u *)"?*$~") != NULL);
}
static void
namelowcpy(
char_u *d,
char_u *s)
{
#ifdef DJGPP
if (USE_LONG_FNAME) /* don't lower case on Windows 95/NT systems */
while (*s)
*d++ = *s++;
else
#endif
while (*s)
*d++ = TO_LOWER(*s++);
*d = NUL;
}
/*
* Recursive function to expand one path section with wildcards.
* Return the number of matches found.
*/
int
mch_expandpath(
struct growarray *gap,
char_u *path,
int flags)
{
char_u *buf;
char_u *p, *s, *e;
int start_len, c;
struct ffblk fb;
int matches;
start_len = gap->ga_len;
buf = alloc(STRLEN(path) + BASENAMELEN + 5); /* make room for file name */
if (buf == NULL)
return 0;
/*
* Find the first part in the path name that contains a wildcard.
* Copy it into buf, including the preceding characters.
*/
p = buf;
s = NULL;
e = NULL;
while (*path)
{
if (*path == '\\' || *path == ':' || *path == '/')
{
if (e)
break;
else
s = p;
}
if (*path == '*' || *path == '?')
e = p;
*p++ = *path++;
}
e = p;
if (s)
s++;
else
s = buf;
/* if the file name ends in "*" and does not contain a ".", addd ".*" */
if (e[-1] == '*' && vim_strchr(s, '.') == NULL)
{
*e++ = '.';
*e++ = '*';
}
/* now we have one wildcard component between s and e */
*e = NUL;
/* If we are expanding wildcards we try both files and directories */
if ((c = findfirst((char *)buf, &fb,
(*path || (flags & EW_DIR)) ? FA_DIREC : 0)) != 0)
{
/* not found */
vim_free(buf);
return 0; /* unexpanded or empty */
}
while (!c)
{
namelowcpy((char *)s, fb.ff_name);
/* ignore "." and ".." */
if (*s != '.' || (s[1] != NUL && (s[1] != '.' || s[2] != NUL)))
{
STRCAT(buf, path);
if (mch_has_wildcard(path))
(void)mch_expandpath(gap, buf, flags);
else if (mch_getperm(buf) >= 0) /* add existing file */
addfile(gap, buf, flags);
}
c = findnext(&fb);
}
vim_free(buf);
matches = gap->ga_len - start_len;
if (matches)
qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches,
sizeof(char_u *), pstrcmp);
return matches;
}
/*
* The normal chdir() does not change the default drive.
* This one does.
*/
int
mch_chdir(char *path)
{
if (path[0] == NUL) /* just checking... */
return 0;
if (path[1] == ':') /* has a drive name */
{
if (change_drive(TO_LOWER(path[0]) - 'a' + 1))
return -1; /* invalid drive name */
path += 2;
}
if (*path == NUL) /* drive name only */
return 0;
return chdir(path); /* let the normal chdir() do the rest */
}
#ifdef DJGPP
/*
* mch_rename() works around a bug in rename (aka MoveFile) in
* Windows 95: rename("foo.bar", "foo.bar~") will generate a
* file whose short file name is "FOO.BAR" (its long file name will
* be correct: "foo.bar~"). Because a file can be accessed by
* either its SFN or its LFN, "foo.bar" has effectively been
* renamed to "foo.bar", which is not at all what was wanted. This
* seems to happen only when renaming files with three-character
* extensions by appending a suffix that does not include ".".
* Windows NT gets it right, however, with an SFN of "FOO~1.BAR".
* This works like mch_rename in os_win32.c, but is a bit simpler.
*
* Like rename(), returns 0 upon success, non-zero upon failure.
* Should probably set errno appropriately when errors occur.
*/
int
mch_rename(const char *OldFile, const char *NewFile)
{
char_u *TempFile;
int retval;
int fd;
/* rename() works correctly without long file names, so use that */
if (!_USE_LFN)
return rename(OldFile, NewFile);
if ((TempFile = alloc((unsigned)(STRLEN(OldFile) + 13))) == NULL)
return -1;
STRCPY(TempFile, OldFile);
STRCPY(gettail(TempFile), "axlqwqhy.ba~");
if (rename(OldFile, TempFile))
retval = -1;
else
{
/* now create an empty file called OldFile; this prevents
* the operating system using OldFile as an alias (SFN)
* if we're renaming within the same directory. For example,
* we're editing a file called filename.asc.txt by its SFN,
* filena~1.txt. If we rename filena~1.txt to filena~1.txt~
* (i.e., we're making a backup while writing it), the SFN
* for filena~1.txt~ will be filena~1.txt, by default, which
* will cause all sorts of problems later in buf_write. So, we
* create an empty file called filena~1.txt and the system will have
* to find some other SFN for filena~1.txt~, such as filena~2.txt
*/
if ((fd = open(OldFile, O_RDWR|O_CREAT|O_EXCL, 0444)) < 0)
return -1;
retval = rename(TempFile, NewFile);
close(fd);
mch_remove((char_u *)OldFile);
}
vim_free(TempFile);
return retval; /* success */
}
#endif
/*
* Special version of getenv(): use $HOME when $VIM not defined.
*/
char_u *
mch_getenv(char_u *var)
{
char_u *retval;
retval = (char_u *)getenv((char *)var);
if (retval == NULL && STRCMP(var, "VIM") == 0)
retval = (char_u *)getenv("HOME");
return retval;
}
#ifdef DJGPP
/*
* setlocale() for DJGPP with MS-DOS codepage support
* Author: Cyril Slobin <slobin@fe.msk.ru>
*
* Scaled down a lot for use by Vim: Only support setlocale(LC_ALL, "").
*/
#undef setlocale
#include <go32.h>
#include <inlines/ctype.ha>
#include <locale.h>
#define UPCASE (__dj_ISALNUM | __dj_ISALPHA | __dj_ISGRAPH | __dj_ISPRINT | __dj_ISUPPER)
#define LOCASE (__dj_ISALNUM | __dj_ISALPHA | __dj_ISGRAPH | __dj_ISPRINT | __dj_ISLOWER)
void
djgpp_setlocale(void)
{
__dpmi_regs regs;
struct { char id; unsigned short off, seg; } __attribute__ ((packed)) info;
unsigned char buffer[0x82], lower, upper;
int i;
regs.x.ax = 0x6502;
regs.x.bx = 0xffff;
regs.x.dx = 0xffff;
regs.x.cx = 5;
regs.x.es = __tb >> 4;
regs.x.di = __tb & 0xf;
__dpmi_int(0x21, ®s);
if (regs.x.flags & 1)
return;
dosmemget(__tb, 5, &info);
dosmemget((info.seg << 4) + info.off, 0x82, buffer);
if (*(short *)buffer != 0x80)
return;
/* Fix problem of underscores being replaced with y-umlaut. (Levin) */
if (buffer[26] == 0x5f)
buffer[26] = 0x98;
for (i = 0; i < 0x80; i++)
{
lower = i + 0x80;
upper = (buffer+2)[i];
if (lower != upper)
{
__dj_ctype_flags[lower+1] = LOCASE;
__dj_ctype_toupper[lower+1] = upper;
if (__dj_ctype_flags[upper+1] == 0)
__dj_ctype_flags[upper+1] = UPCASE;
if (__dj_ctype_tolower[upper+1] == upper)
__dj_ctype_tolower[upper+1] = lower;
}
}
return;
}
#endif /* DJGPP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -