⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_msdos.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
	}
    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, &regs);

    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 + -