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

📄 message.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* vi:set ts=8 sts=4 sw=4:
 *
 * VIM - Vi IMproved	by Bram Moolenaar
 *
 * Do ":help uganda"  in Vim to read copying and usage conditions.
 * Do ":help credits" in Vim to see a list of people who contributed.
 */

/*
 * message.c: functions for displaying messages on the command line
 */

#define MESSAGE_FILE		/* don't include prototype for smsg() */

#include "vim.h"

#ifdef __QNX__
# include <stdarg.h>
#endif

static void msg_home_replace_attr __ARGS((char_u *fname, int attr));
static int  msg_use_printf __ARGS((void));
static void msg_screen_putchar __ARGS((int c, int attr));
static int  msg_check_screen __ARGS((void));
static void redir_write __ARGS((char_u *s));
#ifdef CON_DIALOG
static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton));
#endif

/*
 * msg(s) - displays the string 's' on the status line
 * When terminal not initialized (yet) mch_errmsg(..) is used.
 * return TRUE if wait_return not called
 */
    int
msg(s)
    char_u	    *s;
{
    return msg_attr(s, 0);
}

    int
msg_attr(s, attr)
    char_u	   *s;
    int		    attr;
{
    static int	    entered = 0;
    int		    retval;

    /*
     * It is possible that displaying a messages causes a problem (e.g.,
     * when redrawing the window), which causes another message, etc..	To
     * break this loop, limit the recursiveness to 3 levels.
     */
    if (entered >= 3)
	return TRUE;
    ++entered;

    msg_start();
    msg_outtrans_attr(s, attr);
    msg_clr_eos();
    retval = msg_end();

    --entered;
    return retval;
}

/*
 * automatic prototype generation does not understand this function
 */
#ifndef PROTO
# ifndef __QNX__

int
#ifdef __BORLANDC__
_RTLENTRYF
#endif
smsg __ARGS((char_u *, long, long, long,
			long, long, long, long, long, long, long));
int
#ifdef __BORLANDC__
_RTLENTRYF
#endif
smsg_attr __ARGS((int, char_u *, long, long, long,
			long, long, long, long, long, long, long));

/* VARARGS */
    int
#ifdef __BORLANDC__
_RTLENTRYF
#endif
smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
    char_u	*s;
    long	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
{
    return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
}

/* VARARGS */
    int
#ifdef __BORLANDC__
_RTLENTRYF
#endif
smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
    int		attr;
    char_u	*s;
    long	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
{
    sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
    return msg_attr(IObuff, attr);
}

# else /* __QNX__ */

int smsg(char_u *s, ...)
{
    va_list arglist;

    va_start(arglist, s);
    vsprintf((char *)IObuff, (char *)s, arglist);
    va_end(arglist);
    return msg(IObuff);
}

int smsg_attr(int attr, char_u *s, ...)
{
    va_list arglist;

    va_start(arglist, s);
    vsprintf((char *)IObuff, (char *)s, arglist);
    va_end(arglist);
    return msg_attr(IObuff, attr);
}

# endif /* __QNX__ */
#endif

/*
 * emsg() - display an error message
 *
 * Rings the bell, if appropriate, and calls message() to do the real work
 * When terminal not initialized (yet) mch_errmsg(..) is used.
 *
 * return TRUE if wait_return not called
 */
    int
emsg(s)
    char_u	   *s;
{
    char_u	    *Buf;
    static int	    last_lnum = 0;
    static char_u   *last_sourcing_name = NULL;
    int		    attr;
    int		    other_sourcing_name;

    if (emsg_off)		/* no error messages at the moment */
	return TRUE;

    if (global_busy)		/* break :global command */
	++global_busy;

    if (p_eb)
	beep_flush();		/* also includes flush_buffers() */
    else
	flush_buffers(FALSE);	/* flush internal buffers */
    did_emsg = TRUE;		/* flag for DoOneCmd() */
    emsg_on_display = TRUE;	/* remember there is an error message */
    ++msg_scroll;		/* don't overwrite a previous message */
    attr = hl_attr(HLF_E);	/* set highlight mode for error messages */
    if (msg_scrolled)
	need_wait_return = TRUE;    /* needed in case emsg() is called after
				     * wait_return has reset need_wait_return
				     * and a redraw is expected because
				     * msg_scrolled is non-zero */

/*
 * First output name and line number of source of error message
 */
    if (sourcing_name != NULL)
    {
	if (last_sourcing_name != NULL)
	    other_sourcing_name = STRCMP(sourcing_name, last_sourcing_name);
	else
	    other_sourcing_name = TRUE;
    }
    else
	other_sourcing_name = FALSE;

    if (sourcing_name != NULL
	    && (other_sourcing_name || sourcing_lnum != last_lnum)
	    && (Buf = alloc(MAXPATHL + 30)) != NULL)
    {
	++no_wait_return;
	if (other_sourcing_name)
	{
	    sprintf((char *)Buf, "Error detected while processing %s:",
					    sourcing_name);
	    msg_attr(Buf, attr);
	}
	    /* lnum is 0 when executing a command from the command line
	     * argument, we don't want a line number then */
	if (sourcing_lnum != 0)
	{
	    sprintf((char *)Buf, "line %4ld:", sourcing_lnum);
	    msg_attr(Buf, hl_attr(HLF_N));
	}
	--no_wait_return;
	last_lnum = sourcing_lnum;  /* only once for each line */
	vim_free(Buf);
    }

    /* remember the last sourcing name printed, also when it's empty */
    if (sourcing_name == NULL || other_sourcing_name)
    {
	vim_free(last_sourcing_name);
	if (sourcing_name == NULL)
	    last_sourcing_name = NULL;
	else
	    last_sourcing_name = vim_strsave(sourcing_name);
    }
    msg_nowait = FALSE;			/* wait for this msg */

#ifdef WANT_EVAL
    set_internal_string_var((char_u *)"errmsg", s);
#endif
    return msg_attr(s, attr);
}

    int
emsg2(s, a1)
    char_u *s, *a1;
{
    if (emsg_off)		/* no error messages at the moment */
	return TRUE;

    /* Check for NULL strings (just in case) */
    if (a1 == NULL)
	a1 = (char_u *)"[NULL]";
    /* Check for very long strings (can happen with ":help ^A<CR>") */
    if (STRLEN(s) + STRLEN(a1) >= (size_t)IOSIZE)
	a1 = (char_u *)"[string too long]";
    sprintf((char *)IObuff, (char *)s, (char *)a1);
    return emsg(IObuff);
}

    int
emsgn(s, n)
    char_u *s;
    long    n;
{
    if (emsg_off)		/* no error messages at the moment */
	return TRUE;
    sprintf((char *)IObuff, (char *)s, n);
    return emsg(IObuff);
}

/*
 * Like msg(), but truncate to a single line if p_shm contains 't', or when
 * "force" is TRUE.
 * Careful: The string may be changed!
 * Returns a pointer to the printed message, if wait_return() not called.
 */
    char_u *
msg_trunc_attr(s, force, attr)
    char_u	*s;
    int		force;
    int		attr;
{
    int		n;

    if ((force || shortmess(SHM_TRUNC)) && (n = (int)STRLEN(s) -
		    (int)(Rows - cmdline_row - 1) * Columns - sc_col + 1) > 0)
    {
	s += n;
	*s = '<';
    }
    if (msg_attr(s, attr))
	return s;
    return NULL;
}

/*
 * wait for the user to hit a key (normally a return)
 * if 'redraw' is TRUE, clear and redraw the screen
 * if 'redraw' is FALSE, just redraw the screen
 * if 'redraw' is -1, don't redraw at all
 */
    void
wait_return(redraw)
    int	    redraw;
{
    int		    c;
    int		    oldState;
    int		    tmpState;

    if (redraw == TRUE)
	must_redraw = CLEAR;

/*
 * With the global command (and some others) we only need one return at the
 * end. Adjust cmdline_row to avoid the next message overwriting the last one.
 * When inside vgetc(), we can't wait for a typed character at all.
 */
    if (vgetc_busy)
	return;
    if (no_wait_return)
    {
	need_wait_return = TRUE;
	if (!exmode_active)
	    cmdline_row = msg_row;
	return;
    }

    redir_off = TRUE;		    /* don't redirect this message */
    oldState = State;
    if (quit_more)
    {
	c = CR;			    /* just pretend CR was hit */
	quit_more = FALSE;
	got_int = FALSE;
    }
    else if (exmode_active)
    {
	MSG_PUTS(" ");	  /* make sure the cursor is on the right line */
	c = CR;			    /* no need for a return in ex mode */
	got_int = FALSE;
    }
    else
    {
	State = HITRETURN;
#ifdef USE_MOUSE
	setmouse();
#endif
	if (msg_didout)		    /* start on a new line */
	    msg_putchar('\n');
	if (got_int)
	    MSG_PUTS("Interrupt: ");

#ifdef ORG_HITRETURN
	MSG_PUTS_ATTR("Press RETURN to continue", hl_attr(HLF_R));
	do {
	    c = vgetc();
	} while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
	if (c == ':')			/* this can vi too (but not always!) */
	    stuffcharReadbuff(c);
#else
	MSG_PUTS_ATTR("Press RETURN or enter command to continue",
							      hl_attr(HLF_R));
	if (!msg_use_printf())
	    msg_clr_eos();
	do
	{
	    c = vgetc();
	    if (!global_busy)
		got_int = FALSE;
	} while (c == Ctrl('C')
#ifdef USE_GUI
				|| c == K_SCROLLBAR || c == K_HORIZ_SCROLLBAR
#endif
#ifdef USE_MOUSE
				|| c == K_LEFTDRAG   || c == K_LEFTRELEASE
				|| c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
				|| c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
				|| c == K_IGNORE     ||
				(!mouse_has(MOUSE_RETURN) &&
				     (c == K_LEFTMOUSE ||
				      c == K_MIDDLEMOUSE ||
				      c == K_RIGHTMOUSE))
#endif
				);
	ui_breakcheck();
#ifdef USE_MOUSE
	/*
	 * Avoid that the mouse-up event causes visual mode to start.
	 */
	if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE)
	    jump_to_mouse(MOUSE_SETPOS, NULL);
	else
#endif
	    if (vim_strchr((char_u *)"\r\n ", c) == NULL)
	{
	    stuffcharReadbuff(c);
	    do_redraw = TRUE;	    /* need a redraw even though there is
				       something in the stuff buffer */
	}
#endif
    }
    redir_off = FALSE;

    /*
     * If the user hits ':', '?' or '/' we get a command line from the next
     * line.
     */
    if (c == ':' || c == '?' || c == '/')
    {
	if (!exmode_active)
	    cmdline_row = msg_row;
	skip_redraw = TRUE;	    /* skip redraw once */
	do_redraw = FALSE;
    }

/*
 * If the window size changed set_winsize() will redraw the screen.
 * Otherwise the screen is only redrawn if 'redraw' is set and no ':' typed.
 */
    tmpState = State;
    State = oldState;		    /* restore State before set_winsize */
#ifdef USE_MOUSE
    setmouse();
#endif
    msg_check();

    /*
     * When switching screens, we need to output an extra newline on exit.
     */
#ifdef UNIX
    if (swapping_screen() && !termcap_active)
	newline_on_exit = TRUE;
#endif

    need_wait_return = FALSE;
    emsg_on_display = FALSE;	/* can delete error message now */
    msg_didany = FALSE;		/* reset lines_left at next msg_start() */
    lines_left = -1;
    if (keep_msg != NULL && linetabsize(keep_msg) >=
				  (Rows - cmdline_row - 1) * Columns + sc_col)
	keep_msg = NULL;	    /* don't redisplay message, it's too long */

    if (tmpState == SETWSIZE)	    /* got resize event while in vgetc() */
    {
	starttermcap();		    /* start termcap before redrawing */
	set_winsize(0, 0, FALSE);
    }
    else if (!skip_redraw && (redraw == TRUE || (msg_scrolled && redraw != -1)))
    {
	starttermcap();		    /* start termcap before redrawing */
	update_screen(VALID);
    }

    dont_wait_return = TRUE;	    /* don't wait again in main() */
}

/*
 * Prepare for outputting characters in the command line.
 */
    void
msg_start()
{
    int		did_return = FALSE;

    keep_msg = NULL;			    /* don't display old message now */
    if (!msg_scroll && full_screen)	    /* overwrite last message */
    {
	msg_row = cmdline_row;
	msg_col = 0;
    }
    else if (msg_didout)		    /* start message on next line */
    {
	msg_putchar('\n');
	did_return = TRUE;
	if (!exmode_active)
	    cmdline_row = msg_row;
    }
    if (!msg_didany)
	lines_left = cmdline_row;
    msg_didout = FALSE;			    /* no output on current line yet */
    cursor_off();

    /* when redirecting, may need to start a new line. */
    if (!did_return)
	redir_write((char_u *)"\n");
}

    void
msg_putchar(c)
    int		c;
{
    msg_putchar_attr(c, 0);
}

    void
msg_putchar_attr(c, attr)
    int		c;
    int		attr;
{
    char_u	buf[4];

    if (IS_SPECIAL(c))
    {
	buf[0] = K_SPECIAL;
	buf[1] = K_SECOND(c);
	buf[2] = K_THIRD(c);
	buf[3] = NUL;
    }
    else
    {
	buf[0] = c;
	buf[1] = NUL;
    }
    msg_puts_attr(buf, attr);
}

    void
msg_outnum(n)
    long	n;
{
    char_u	buf[20];

    sprintf((char *)buf, "%ld", n);
    msg_puts(buf);
}

    void
msg_home_replace(fname)
    char_u	*fname;
{
    msg_home_replace_attr(fname, 0);
}

    void
msg_home_replace_hl(fname)
    char_u	*fname;
{
    msg_home_replace_attr(fname, hl_attr(HLF_D));
}

    static void
msg_home_replace_attr(fname, attr)
    char_u  *fname;
    int	    attr;
{
    char_u	*name;

    name = home_replace_save(NULL, fname);
    if (name != NULL)
	msg_outtrans_attr(name, attr);
    vim_free(name);
}

/*
 * Output 'len' characters in 'str' (including NULs) with translation
 * if 'len' is -1, output upto a NUL character.
 * Use attributes 'attr'.
 * Return the number of characters it takes on the screen.
 */
    int
msg_outtrans(str)
    char_u	    *str;
{
    return msg_outtrans_attr(str, 0);

⌨️ 快捷键说明

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