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

📄 os_msdos.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Get a characters from the keyboard.
 * If time == 0 do not wait for characters.
 * If time == n wait a short time for characters.
 * If time == -1 wait forever for characters.
 *
 * return the number of characters obtained
 */
    int
mch_inchar(
    char_u	*buf,
    int		maxlen,
    long	time)
{
    int		len = 0;
    int		c;
    static int	nextchar = 0;	    /* may keep character when maxlen == 1 */

/*
 * if we got a ctrl-C when we were busy, there will be a "^C" somewhere
 * on the sceen, so we need to redisplay it.
 */
    if (delayed_redraw)
    {
	delayed_redraw = FALSE;
	update_screen(CLEAR);
	setcursor();
	out_flush();
    }

    /* return remaining character from last call */
    if (nextchar)
    {
	*buf = nextchar;
	nextchar = 0;
	return 1;
    }

#ifdef USE_MOUSE
    if (time != 0)
	show_mouse(TRUE);
#endif
    if (time >= 0)
    {
	if (WaitForChar(time) == 0)	/* no character available */
	{
#ifdef USE_MOUSE
	    show_mouse(FALSE);
#endif
	    return 0;
	}
    }
    else    /* time == -1 */
    {
    /*
     * If there is no character available within 2 seconds (default)
     * write the autoscript file to disk
     */
	if (WaitForChar(p_ut) == 0)
	    updatescript(0);
    }
    WaitForChar(FOREVER);	/* wait for key or mouse click */

/*
 * Try to read as many characters as there are, until the buffer is full.
 */
    /*
     * we will get at least one key. Get more if they are available
     * After a ctrl-break we have to read a 0 (!) from the buffer.
     * bioskey(1) will return 0 if no key is available and when a
     * ctrl-break was typed. When ctrl-break is hit, this does not always
     * implies a key hit.
     */
    cbrk_pressed = FALSE;
#ifdef USE_MOUSE
    if (mouse_click >= 0 && maxlen >= 5)
    {
	len = 5;
	*buf++ = ESC + 128;
	*buf++ = 'M';
	*buf++ = mouse_click;
	*buf++ = mouse_x + '!';
	*buf++ = mouse_y + '!';
	mouse_click = -1;
    }
    else
#endif
    {
#ifdef USE_MOUSE
	mouse_hidden = TRUE;
#endif
	if (p_biosk)
	{
	    while ((len == 0 || bioskey(1)) && len < maxlen)
	    {
		c = bioskey(0);		/* get the key */
		/*
		 * translate a few things for inchar():
		 * 0x0000 == CTRL-break		-> 3	(CTRL-C)
		 * 0x0300 == CTRL-@		-> NUL
		 * 0xnn00 == extended key code	-> K_NUL, nn
		 * K_NUL			-> K_NUL, 3
		 */
		if (c == 0)
		    c = 3;
		else if (c == 0x0300)
		    c = NUL;
		else if ((c & 0xff) == 0 || c == K_NUL)
		{
		    if (c == K_NUL)
			c = 3;
		    else
			c >>= 8;
		    *buf++ = K_NUL;
		    ++len;
		}

		if (len < maxlen)
		{
		    *buf++ = c;
		    len++;
		}
		else
		    nextchar = c;
	    }
	}
	else
	{
	    while ((len == 0 || kbhit()) && len < maxlen)
	    {
		switch (c = getch())
		{
		    case 0:
			/* NUL means that there is another character.
			 * Get it immediately, because kbhit() doesn't always
			 * return TRUE for the second character.
			 */
			*buf++ = K_NUL;
			++len;
			c = getch();
			break;
		    case K_NUL:
			*buf++ = K_NUL;
			++len;
			c = 3;
			break;
		    case 3:
			cbrk_pressed = TRUE;
			/*FALLTHROUGH*/
		    default:
			break;
		}
		if (len < maxlen)
		{
		    *buf++ = c;
		    ++len;
		}
		else
		    nextchar = c;
	    }
	}
    }
#ifdef USE_MOUSE
    show_mouse(FALSE);
#endif

    beep_count = 0;	    /* may beep again now that we got some chars */
    return len;
}

/*
 * return non-zero if a character is available
 */
    int
mch_char_avail(void)
{
    return WaitForChar(0L);
}

#ifdef DJGPP
# define INT_ARG    int
#else
# define INT_ARG
#endif

/*
 * function for ctrl-break interrupt
 */
    static void interrupt
#ifdef DJGPP
catch_cbrk(int a)
#else
catch_cbrk(void)
#endif
{
    cbrk_pressed = TRUE;
    ctrlc_pressed = TRUE;
}

/*
 * ctrl-break handler for DOS. Never called when a ctrl-break is typed, because
 * we catch interrupt 1b. If you type ctrl-C while Vim is waiting for a
 * character this function is not called. When a ctrl-C is typed while Vim is
 * busy this function may be called. By that time a ^C has been displayed on
 * the screen, so we have to redisplay the screen. We can't do that here,
 * because we may be called by DOS. The redraw is in mch_inchar().
 */
    static int _cdecl
cbrk_handler(void)
{
    delayed_redraw = TRUE;
    return 1;		    /* resume operation after ctrl-break */
}

/*
 * function for critical error interrupt
 * For DOS 1 and 2 return 0 (Ignore).
 * For DOS 3 and later return 3 (Fail)
 */
    static void interrupt
catch_cint(bp, di, si, ds, es, dx, cx, bx, ax)
    unsigned bp, di, si, ds, es, dx, cx, bx, ax;
{
    ax = (ax & 0xff00);	    /* set AL to 0 */
    if (_osmajor >= 3)
	ax |= 3;	    /* set AL to 3 */
}

/*
 * Set the interrupt vectors for use with Vim on or off.
 * on == TRUE means as used within Vim
 */
    static void
set_interrupts(int on)
{
    static int saved_cbrk;
#ifndef DJGPP
    static void interrupt (*old_cint)();
#endif
    static void interrupt (*old_cbrk)(INT_ARG);

    if (on)
    {
	saved_cbrk = getcbrk();		/* save old ctrl-break setting */
	setcbrk(0);			/* do not check for ctrl-break */
#ifdef DJGPP
	old_cbrk = signal(SIGINT, catch_cbrk);	/* critical error interrupt */
#else
	old_cint = getvect(0x24);	/* save old critical error interrupt */
	setvect(0x24, catch_cint);	/* install our critical error interrupt */
	old_cbrk = getvect(0x1B);	/* save old ctrl-break interrupt */
	setvect(0x1B, catch_cbrk);	/* install our ctrl-break interrupt */
	ctrlbrk(cbrk_handler);		/* vim's ctrl-break handler */
#endif
	if (term_console)
	    out_str(T_ME);		/* set colors */
    }
    else
    {
	setcbrk(saved_cbrk);		/* restore ctrl-break setting */
#ifdef DJGPP
	signal(SIGINT,old_cbrk);	/* critical error interrupt */
#else
	setvect(0x24, old_cint);	/* restore critical error interrupt */
	setvect(0x1B, old_cbrk);	/* restore ctrl-break interrupt */
#endif
	/* restore ctrl-break handler, how ??? */
	if (term_console)
	    mynormvideo();		/* restore screen colors */
    }
}

/*
 * We have no job control, fake it by starting a new shell.
 */
    void
mch_suspend(void)
{
    suspend_shell();
}

extern int _fmode;

/*
 * Prepare window for use by Vim.
 * we do not use windows, there is not much to do here
 */
    void
mch_windinit(void)
{
    union REGS regs;

    term_console = TRUE;    /* assume using the console for the things here */
    _fmode = O_BINARY;	    /* we do our own CR-LF translation */
    out_flush();
    set_interrupts(TRUE);   /* catch interrupts */

#ifdef DJGPP
    /*
     * Use Long File Names by default, if $LFN not set.
     */
    if (getenv("LFN") == NULL)
	putenv("LFN=y");

    get_screenbase();
#endif

#ifdef USE_MOUSE
/* find out if a MS compatible mouse is available */
    regs.x.ax = 0;
    (void)int86(0x33, &regs, &regs);
    mouse_avail = regs.x.ax;
    /* best guess for mouse coordinate computations */
    mch_get_winsize();
    if (Columns <= 40)
	mouse_x_div = 16;
    if (Rows == 30)
	mouse_y_div = 16;
#endif

    /*
     * Try switching to 16 colors for background, instead of 8 colors and
     * blinking.  Does this always work?  Can the old value be restored?
     */
    regs.x.ax = 0x1003;
    regs.h.bl = 0x00;
    regs.h.bh = 0x00;
    int86(0x10, &regs, &regs);

    /* Save the old cursor shape */
    mch_restore_cursor_shape(FALSE);
    /* Initialise the cursor shape */
    mch_update_cursor();
}

    int
mch_check_win(
    int		argc,
    char	**argv)
{
    /* store argv[0], may be used for $VIM */
    if (*argv[0] != NUL)
	exe_name = FullName_save((char_u *)argv[0], FALSE);

    if (isatty(1))
	return OK;
    return FAIL;
}

/*
 * Return TRUE if the input comes from a terminal, FALSE otherwise.
 */
    int
mch_input_isatty(void)
{
    if (isatty(read_cmd_fd))
	return TRUE;
    return FALSE;
}

#ifdef USE_FNAME_CASE
/*
 * fname_case(): Set the case of the file name, if it already exists.
 */
    void
fname_case(char_u *name)
{
    char_u	    *tail;
    struct ffblk    fb;

    slash_adjust(name);
    if (findfirst(name, &fb, 0) == 0)
    {
	tail = gettail(name);
	if (STRLEN(tail) == STRLEN(fb.ff_name))
	    STRCPY(tail, fb.ff_name);
    }
}
#endif

/*
 * mch_settitle(): set titlebar of our window.
 * Dos console has no title.
 */
    void
mch_settitle(
    char_u *title,
    char_u *icon)
{
}

/*
 * Restore the window/icon title. (which we don't have)
 */
    void
mch_restore_title(int which)
{
}

    int
mch_can_restore_title(void)
{
    return FALSE;
}

    int
mch_can_restore_icon(void)
{
    return FALSE;
}

/*
 * Insert user name in s[len].
 */
    int
mch_get_user_name(
    char_u	*s,
    int		len)
{
    *s = NUL;
    return FAIL;
}

/*
 * Insert host name is s[len].
 */
    void
mch_get_host_name(
    char_u	*s,
    int		len)
{
#ifdef DJGPP
    STRNCPY(s, "PC (32 bits Vim)", len);
#else
    STRNCPY(s, "PC (16 bits Vim)", len);
#endif
}

/*
 * return process ID
 */
    long
mch_get_pid(void)
{
    return (long)0;
}

/*
 * 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)
{
#ifdef DJGPP
    if (getcwd((char *)buf, len) == NULL)
	return FAIL;
    /* turn the '/'s returned by DJGPP into '\'s */
    slash_adjust(buf);
    return OK;
#else
    return (getcwd((char *)buf, len) != NULL ? OK : FAIL);
#endif
}

/*
 * Change default drive (just like _chdrive of Borland C 3.1)
 */
    static int
change_drive(int drive)
{
    union REGS regs;

    regs.h.ah = 0x0e;
    regs.h.dl = drive - 1;
    intdos(&regs, &regs);   /* set default drive */
    regs.h.ah = 0x19;
    intdos(&regs, &regs);   /* get default drive */
    if (regs.h.al == drive - 1)
	return 0;
    else
	return -1;
}

/*
 * Get absolute file name into buffer 'buf' of length 'len' bytes.
 * All slashes are replaced with backslashes, to avoid trouble when comparing
 * file names.
 *
 * return FAIL for failure, OK otherwise
 */
    int
mch_FullName(
    char_u	*fname,
    char_u	*buf,
    int		len,
    int		force)
{
    if (fname == NULL)	/* always fail */
    {
	*buf = NUL;
	return FAIL;
    }

    if (!force && mch_isFullName(fname))	/* allready expanded */
    {
	STRNCPY(buf, fname, len);
	slash_adjust(buf);
	return OK;
    }

#ifdef __BORLANDC__	/* the old Turbo C does not have this */
    if (_fullpath((char *)buf, (char *)fname, len - 1) == NULL)
    {
	STRNCPY(buf, fname, len);   /* failed, use the relative path name */
	slash_adjust(buf);
	return FAIL;
    }
    if (mch_isdir(fname))
	STRCAT(buf, "\\");
    slash_adjust(buf);
    return OK;
#else			/* almost the same as mch_FullName in os_unix.c */
    {
	int	l;
	char_u	olddir[MAXPATHL];
	char_u	*p, *q;
	int	c;
	int	retval = OK;

	*buf = 0;
	/*
	 * change to the directory for a moment,
	 * and then do the getwd() (and get back to where we were).
	 * This will get the correct path name with "../" things.
	 */
	p = vim_strrchr(fname, '/');
	q = vim_strrchr(fname, '\\');
	if (q != NULL && (p == NULL || q > p))
	    p = q;
	q = vim_strrchr(fname, ':');
	if (q != NULL && (p == NULL || q > p))
	    p = q;
	if (p != NULL)
	{
	    if (getcwd(olddir, MAXPATHL) == NULL)
	    {
		p = NULL;	/* can't get current dir: don't chdir */
		retval = FAIL;
	    }
	    else
	    {
		if ((q + 1) == p)		/* ... c:\foo	    */
		    q = p + 1;			/* -> c:\	    */
		else				/* but c:\foo\bar   */
		    q = p;			/* -> c:\foo	    */

		c = *q;			/* truncate at start of fname */
		*q = NUL;
#ifdef DJGPP
		STRCPY(buf, fname);
		slash_adjust(buf);	/* needed when fname starts with \ */
		if (mch_chdir(buf))	/* change to the directory */
#else
		if (mch_chdir(fname))	/* change to the directory */
#endif
		    retval = FAIL;
		else
		{
		    fname = q;
		    if (c == '\\')	    /* if we cut the name at a */
			fname++;	    /* '\', don't add it again */
		}
		*q = c;
	    }
	}
	if (getcwd(buf, len) == NULL)
	{
	    retval = FAIL;
	    *buf = NUL;
	}
	/*
	 * Concatenate the file name to the path.
	 */
	l = STRLEN(buf);
	if (l && buf[l - 1] != '/' && buf[l - 1] != '\\')
	    strcat(buf, "/");
	if (p)
	    mch_chdir(olddir);
	strcat(buf, fname);
	slash_adjust(buf);
	return retval;
    }
#endif
}

/*
 * 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(char_u *p)
{
#ifdef OLD_DJGPP    /* this seems to have been fixed in DJGPP 2.01 */
    /* DJGPP can't handle a file name that starts with a backslash, and when it
     * starts with a slash there should be no backslashes */
    if (*p == '\\' || *p == '/')
	while (*p)
	{
	    if (*p == '\\')
		*p = '/';
	    ++p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -