📄 message.c
字号:
{
screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ', 0);
screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
}
}
/*
* Clear the command line.
*/
void
msg_clr_cmdline()
{
msg_row = cmdline_row;
msg_col = 0;
msg_clr_eos();
}
/*
* end putting a message on the screen
* call wait_return if the message does not fit in the available space
* return TRUE if wait_return not called.
*/
int
msg_end()
{
/*
* if the string is larger than the window,
* or the ruler option is set and we run into it,
* we have to redraw the window.
* Do not do this if we are abandoning the file or editing the command line.
*/
if (!exiting && msg_check() && State != CMDLINE)
{
wait_return(FALSE);
return FALSE;
}
out_flush();
return TRUE;
}
/*
* If the written message has caused the screen to scroll up, or if we
* run into the shown command or ruler, we have to redraw the window later.
*/
int
msg_check()
{
if (msg_scrolled || (msg_row == Rows - 1 && msg_col >= sc_col))
{
redraw_all_later(NOT_VALID);
redraw_cmdline = TRUE;
return TRUE;
}
return FALSE;
}
/*
* May write a string to the redirection file.
*/
static void
redir_write(s)
char_u *s;
{
static int cur_col = 0;
if (redir_fd != NULL && !redir_off)
{
/* If the string doesn't start with CR or NL, go to msg_col */
if (*s != '\n' && *s != '\r')
{
while (cur_col < msg_col)
{
fputs(" ", redir_fd);
++cur_col;
}
}
fputs((char *)s, redir_fd);
/* Adjust the current column */
while (*s)
{
if (*s == '\r' || *s == '\n')
cur_col = 0;
else if (*s == '\t')
cur_col += (8 - cur_col % 8);
else
++cur_col;
++s;
}
}
}
/*
* Give a warning message (for searching).
* Use 'w' highlighting and may repeat the message after redrawing
*/
void
give_warning(message, hl)
char_u *message;
int hl;
{
keep_msg = NULL;
if (hl)
keep_msg_attr = hl_attr(HLF_W);
else
keep_msg_attr = 0;
if (msg_attr(message, keep_msg_attr) && !msg_scrolled)
keep_msg = message;
msg_didout = FALSE; /* overwrite this message */
msg_nowait = TRUE; /* don't wait for this message */
msg_col = 0;
}
/*
* Advance msg cursor to column "col".
*/
void
msg_advance(col)
int col;
{
if (col >= Columns) /* not enough room */
col = Columns - 1;
while (msg_col < col)
msg_putchar(' ');
}
#if defined(CON_DIALOG) || defined(PROTO)
/*
* Used for "confirm()" function, and the :confirm command prefix.
* Versions which haven't got flexible dialogs yet, and console
* versions, get this generic handler which uses the command line.
*
* type = one of:
* VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
* title = title string (can be NULL for default)
* (neither used in console dialogs at the moment)
*
* Format of the "buttons" string:
* "Button1Name\nButton2Name\nButton3Name"
* The first button should normally be the default/accept
* The second button should be the 'Cancel' button
* Other buttons- use your imagination!
* A '&' in a button name becomes a shortcut, so each '&' should be before a
* different letter.
*/
/* ARGSUSED */
int
do_dialog(type, title, message, buttons, dfltbutton)
int type;
char_u *title;
char_u *message;
char_u *buttons;
int dfltbutton;
{
int oldState;
char_u buf[20]; /* for getting keystrokes */
int retval = 0;
char_u *hotkeys;
#ifndef NO_CONSOLE
/* Don't output anything in silent mode ("ex -s") */
if (silent_mode)
return dfltbutton; /* return default option */
#endif
#ifdef GUI_DIALOG
/* When GUI is running, use the GUI dialog */
if (gui.in_use)
return gui_mch_dialog(type, title, message, buttons, dfltbutton);
#endif
oldState = State;
State = CONFIRM;
#ifdef USE_MOUSE
setmouse();
#endif
/*
* Since we wait for a keypress, don't make the
* user press RETURN as well afterwards.
*/
++no_wait_return;
hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
if (hotkeys != NULL)
{
for (;;)
{
/*
* Get a typed character directly from the user.
* Don't use vgetc(), it syncs undo and eats mapped
* characters. Disadvantage: Special keys and mouse
* cannot be used here, typeahead is ignored.
*/
cursor_on();
out_flush();
(void)ui_inchar(buf, 20, -1L);
switch (buf[0])
{
case CR: /* User accepts default option */
case NL:
retval = dfltbutton;
break;
case Ctrl('C'): /* User aborts/cancels */
case ESC:
retval = 0;
break;
default: /* Could be a hotkey? */
#ifdef UNIX
if (buf[0] == intr_char)
{
retval = 0; /* another way of cancelling */
break;
}
#endif
for (retval = 0; hotkeys[retval]; retval++)
{
if (hotkeys[retval] == TO_LOWER(buf[0]))
break;
}
if (hotkeys[retval])
{
retval++;
break;
}
/* No hotkey match, so keep waiting */
continue;
}
break;
}
vim_free(hotkeys);
}
State = oldState;
#ifdef USE_MOUSE
setmouse();
#endif
--no_wait_return;
need_wait_return = FALSE;
dont_wait_return = TRUE; /* don't wait again in main() */
return retval;
}
char_u *confirm_msg = NULL; /* ":confirm" message */
/*
* Format the dialog string, and display it at the bottom of
* the screen. Return a string of hotkey chars (if defined) for
* each 'button'. If a button has no hotkey defined, the string
* has the buttons first letter.
*
* Returns allocated array, or NULL for error.
*
*/
static char_u *
msg_show_console_dialog(message, buttons, dfltbutton)
char_u *message;
char_u *buttons;
int dfltbutton;
{
int len = 0;
int lenhotkey = 1; /*first button*/
char_u *hotk;
char_u *p;
char_u *q;
char_u *r;
/*
* First compute how long a string we need to allocate for the message.
*/
r = buttons;
while (*r)
{
if (*r == DLG_BUTTON_SEP)
{
len++; /* '\n' -> ', ' */
lenhotkey++; /* each button needs a hotkey */
}
else if (*r == DLG_HOTKEY_CHAR)
{
len++; /* '&a' -> '[a]' */
}
r++;
}
len += STRLEN(message)
+ 2 /* for the NL's */
+ STRLEN(buttons)
+ 3; /* for the ": " and NUL */
lenhotkey++; /* for the NUL */
/*
* Now allocate and load the strings
*/
vim_free(confirm_msg);
confirm_msg = alloc(len);
if (confirm_msg == NULL)
return NULL;
*confirm_msg = NUL;
hotk = alloc(lenhotkey);
if (hotk == NULL)
return NULL;
*confirm_msg = '\n';
STRCPY(confirm_msg + 1, message);
p = confirm_msg + 1 + STRLEN(message);
q = hotk;
r = buttons;
*q = (char_u)TO_LOWER(*r); /* define lowercase hotkey */
*p++ = '\n';
while (*r)
{
if (*r == DLG_BUTTON_SEP)
{
*p++ = ',';
*p++ = ' '; /* '\n' -> ', ' */
*(++q) = (char_u)TO_LOWER(*(r + 1)); /* next hotkey */
if (dfltbutton)
--dfltbutton;
}
else if (*r == DLG_HOTKEY_CHAR)
{
r++;
if (*r == DLG_HOTKEY_CHAR) /* duplicate magic = literal */
*p++ = *r;
else
{
/* '&a' -> '[a]' */
*p++ = (dfltbutton == 1) ? '[' : '(';
*p++ = *r;
*p++ = (dfltbutton == 1) ? ']' : ')';
*q = (char_u)TO_LOWER(*r); /* define lowercase hotkey */
}
}
else
{
*p++ = *r; /* everything else copy literally */
}
r++;
}
*p++ = ':';
*p++ = ' ';
*p = NUL;
*(++q) = NUL;
display_confirm_msg();
return hotk;
}
/*
* Display the ":confirm" message. Also called when screen resized.
*/
void
display_confirm_msg()
{
if (confirm_msg != NULL)
msg_puts_attr(confirm_msg, hl_attr(HLF_M));
}
#endif /* CON_DIALOG */
#if defined(CON_DIALOG) || defined(GUI_DIALOG)
/*
* Various stock dialogs used throughout Vim when :confirm is used.
*/
#if 0 /* not used yet */
void
vim_dialog_ok(type, title, message)
int type;
char_u *title;
char_u *message;
{
(void)do_dialog(type,
title == NULL ? (char_u *)"Information" : title,
message,
(char_u *)"&OK", 1);
}
#endif
#if 0 /* not used yet */
int
vim_dialog_okcancel(type, title, message, dflt)
int type;
char_u *title;
char_u *message;
int dflt;
{
if (do_dialog(type,
title == NULL ? (char_u *)"Confirmation" : title,
message,
(char_u *)"&OK\n&Cancel", dflt) == 1)
return VIM_OK;
return VIM_CANCEL;
}
#endif
int
vim_dialog_yesno(type, title, message, dflt)
int type;
char_u *title;
char_u *message;
int dflt;
{
if (do_dialog(type,
title == NULL ? (char_u *)"Question" : title,
message,
(char_u *)"&Yes\n&No", dflt) == 1)
return VIM_YES;
return VIM_NO;
}
int
vim_dialog_yesnocancel(type, title, message, dflt)
int type;
char_u *title;
char_u *message;
int dflt;
{
switch (do_dialog(type,
title == NULL ? (char_u *)"Question" : title,
message,
(char_u *)"&Yes\n&No\n&Cancel", dflt))
{
case 1: return VIM_YES;
case 2: return VIM_NO;
}
return VIM_CANCEL;
}
int
vim_dialog_yesnoallcancel(type, title, message, dflt)
int type;
char_u *title;
char_u *message;
int dflt;
{
switch (do_dialog(type,
title == NULL ? (char_u *)"Question" : title,
message,
(char_u *)"&Yes\n&No\nSave &All\n&Discard All\n&Cancel", dflt))
{
case 1: return VIM_YES;
case 2: return VIM_NO;
case 3: return VIM_ALL;
case 4: return VIM_DISCARDALL;
}
return VIM_CANCEL;
}
#endif /* GUI_DIALOG || CON_DIALOG */
#if defined(USE_BROWSE) || defined(PROTO)
/*
* Generic browse function. Calls gui_mch_browse() when possible.
* Later this may pop-up a non-GUI file selector (external command?).
*/
char_u *
do_browse(saving, title, dflt, ext, initdir, filter, buf)
int saving; /* write action */
char_u *title; /* title for the window */
char_u *dflt; /* default file name */
char_u *ext; /* extension added */
char_u *initdir; /* initial directory, NULL for current dir */
char_u *filter; /* file name filter */
BUF *buf; /* buffer to read/write for */
{
char_u *fname;
static char_u *last_dir = NULL; /* last used directory */
char_u *tofree = NULL;
/* Must turn off browse straight away, or :so autocommands will get the
* flag too! */
browse = FALSE;
if (title == NULL)
{
if (saving)
title = (char_u *)"Save File dialog";
else
title = (char_u *)"Open File dialog";
}
/* When no directory specified, use buffer dir, last dir or current dir */
if (initdir == NULL || *initdir == NUL)
{
/* When saving or 'browsedir' is "buffer", use buffer fname */
if ((saving || *p_bsdir == 'b') && buf != NULL && buf->b_ffname != NULL)
{
dflt = gettail(curbuf->b_ffname);
tofree = vim_strsave(curbuf->b_ffname);
if (tofree != NULL)
{
initdir = tofree;
*gettail(initdir) = NUL;
}
}
/* When 'browsedir' is "last", use dir from last browse */
else if (*p_bsdir == 'l')
initdir = last_dir;
/* When 'browsedir is "current", use current directory. This is the
* default already, leave initdir empty. */
}
# ifdef USE_GUI
if (gui.in_use) /* when this changes, also adjust f_has()! */
{
fname = gui_mch_browse(saving, title, dflt, ext, initdir, filter);
}
else
# endif
{
/* TODO: non-GUI file selector here */
fname = NULL;
}
/* keep the directory for next time */
if (fname != NULL)
{
vim_free(last_dir);
last_dir = vim_strsave(fname);
if (last_dir != NULL)
{
*gettail(last_dir) = NUL;
if (*last_dir == NUL)
{
/* filename only returned, must be in current dir*/
vim_free(last_dir);
last_dir = alloc(MAXPATHL);
if (last_dir != NULL)
mch_dirname(last_dir, MAXPATHL);
}
}
}
vim_free(tofree);
return fname;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -