📄 misc1.c
字号:
* return the 'y' or 'n'
*/
int
ask_yesno(str, direct)
char_u *str;
int direct;
{
int r = ' ';
char_u buf[20];
int len = 0;
int idx = 0;
int save_State = State;
if (exiting) /* put terminal in raw mode for this question */
settmode(TMODE_RAW);
++no_wait_return;
#ifdef USE_GUI_WIN32
dont_scroll = TRUE; /* disallow scrolling here */
#endif
State = CONFIRM; /* mouse behaves like with :confirm */
#ifdef USE_MOUSE
setmouse(); /* disables mouse for xterm */
#endif
while (r != 'y' && r != 'n')
{
/* same highlighting as for wait_return */
smsg_attr(hl_attr(HLF_R), (char_u *)"%s (y/n)?", str);
if (direct)
{
out_flush();
if (idx >= len)
{
len = ui_inchar(buf, 20, -1L);
idx = 0;
}
r = buf[idx++];
}
else
r = vgetc();
if (r == Ctrl('C') || r == ESC)
r = 'n';
msg_putchar(r); /* show what you typed */
out_flush();
}
--no_wait_return;
State = save_State;
#ifdef USE_MOUSE
setmouse();
#endif
return r;
}
/*
* get a number from the user
*/
int
get_number(colon)
int colon; /* allow colon to abort */
{
int n = 0;
int c;
#ifdef USE_GUI_WIN32
dont_scroll = TRUE; /* disallow scrolling here */
#endif
for (;;)
{
windgoto(msg_row, msg_col);
c = vgetc();
if (vim_isdigit(c))
{
n = n * 10 + c - '0';
msg_putchar(c);
}
else if (c == K_DEL || c == K_BS || c == Ctrl('H'))
{
n /= 10;
MSG_PUTS("\b \b");
}
else if (n == 0 && c == ':' && colon)
{
stuffcharReadbuff(':');
if (!exmode_active)
cmdline_row = msg_row;
skip_redraw = TRUE; /* skip redraw once */
do_redraw = FALSE;
break;
}
else if (c == CR || c == NL || c == Ctrl('C') || c == ESC)
break;
}
return n;
}
void
msgmore(n)
long n;
{
long pn;
if (global_busy || /* no messages now, wait until global is finished */
keep_msg || /* there is a message already, skip this one */
!messaging()) /* 'lazyredraw' set, don't do messages now */
return;
if (n > 0)
pn = n;
else
pn = -n;
if (pn > p_report)
{
sprintf((char *)msg_buf, "%ld %s line%s %s",
pn, n > 0 ? "more" : "fewer", plural(pn),
got_int ? "(Interrupted)" : "");
if (msg(msg_buf))
{
keep_msg = msg_buf;
keep_msg_attr = 0;
}
}
}
/*
* flush map and typeahead buffers and give a warning for an error
*/
void
beep_flush()
{
flush_buffers(FALSE);
vim_beep();
}
/*
* give a warning for an error
*/
void
vim_beep()
{
if (p_vb)
{
out_str(T_VB);
}
else
{
#ifdef MSDOS
/*
* The number of beeps outputted is reduced to avoid having to wait
* for all the beeps to finish. This is only a problem on systems
* where the beeps don't overlap.
*/
if (beep_count == 0 || beep_count == 10)
{
out_char('\007');
beep_count = 1;
}
else
++beep_count;
#else
out_char('\007');
#endif
}
}
/*
* To get the "real" home directory:
* - get value of $HOME
* For Unix:
* - go to that directory
* - do mch_dirname() to get the real name of that directory.
* This also works with mounts and links.
* Don't do this for MS-DOS, it will change the "current dir" for a drive.
*/
static char_u *homedir = NULL;
void
init_homedir()
{
char_u *var;
var = mch_getenv((char_u *)"HOME");
#if defined(OS2) || defined(MSDOS) || defined(WIN32)
/*
* Default home dir is C:/
* Best assumption we can make in such a situation.
*/
if (var == NULL)
var = "C:/";
#endif
if (var != NULL)
{
#ifdef UNIX
if (mch_dirname(NameBuff, MAXPATHL) == OK)
{
if (!mch_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK)
var = IObuff;
mch_chdir((char *)NameBuff);
}
#endif
homedir = vim_strsave(var);
}
}
/*
* Expand environment variable with path name.
* "~/" is also expanded, using $HOME. For Unix "~user/" is expanded.
* If anything fails no expansion is done and dst equals src.
*/
void
expand_env(src, dst, dstlen)
char_u *src; /* input string e.g. "$HOME/vim.hlp" */
char_u *dst; /* where to put the result */
int dstlen; /* maximum length of the result */
{
char_u *tail;
int c;
char_u *var;
int copy_char;
int mustfree; /* var was allocated, need to free it later */
char_u *p;
int at_start = TRUE;
src = skipwhite(src);
--dstlen; /* leave one char space for "\," */
while (*src && dstlen > 0)
{
copy_char = TRUE;
if (*src == '$' || (*src == '~' && at_start))
{
mustfree = FALSE;
/*
* The variable name is copied into dst temporarily, because it may
* be a string in read-only memory and a NUL needs to be inserted.
*/
if (*src == '$') /* environment var */
{
tail = src + 1;
var = dst;
c = dstlen - 1;
#ifdef UNIX
/* Unix has ${var-name} type environment vars */
if (*tail == '{' && !vim_isIDc('{'))
{
tail++; /* ignore '{' */
while (c-- > 0 && *tail && *tail != '}')
*var++ = *tail++;
tail++; /* ignore '}' */
}
else
#endif
{
while (c-- > 0 && *tail && vim_isIDc(*tail))
{
#ifdef OS2 /* env vars only in uppercase */
*var++ = TO_UPPER(*tail);
tail++; /* toupper() may be a macro! */
#else
*var++ = *tail++;
#endif
}
}
*var = NUL;
#if defined(OS2) || defined(MSDOS) || defined(WIN32)
/* use "C:/" when $HOME is not set */
if (STRCMP(dst, "HOME") == 0)
var = homedir;
else
#endif
{
var = mch_getenv(dst);
/*
* When expanding $VIM fails, try using the directory name
* from 'helpfile'.
*/
if (var == NULL && STRCMP(dst, "VIM") == 0)
{
p = NULL;
if (vim_strchr(p_hf, '$') == NULL)
p = p_hf;
#ifdef USE_EXE_NAME
/*
* Use the name of the executable, obtained from
* argv[0].
*/
else
{
p = exe_name;
# ifdef MSDOS
/*
* Try the DOS search path. The executable may in
* fact be called differently, so try this last.
*/
if (p == NULL || *p == NUL)
p = searchpath("vim.exe");
# endif
}
#endif
if (p != NULL)
{
char_u *pend;
/* remove the file name */
pend = gettail(p);
/* remove "doc/" from 'helpfile', if present */
if (p == p_hf && pend - 4 >= p
&& fnamencmp(pend - 4, "doc", 3) == 0
&& (pend - 4 == p
|| vim_ispathsep(pend[-5])))
pend -= 4;
#ifdef USE_EXE_NAME
/* remove "src/" from exe_name, if present */
if (p == exe_name)
{
if (pend - 4 >= p
&& fnamencmp(pend - 4, "src", 3) == 0
&& (pend - 4 == p
|| vim_ispathsep(pend[-5])))
pend -= 4;
}
#endif
#ifndef macintosh
/* remove trailing path separator */
if (pend > p && vim_ispathsep(pend[-1]))
--pend;
#endif
var = vim_strnsave(p, (int)(pend - p));
mustfree = TRUE;
if (!mch_isdir(var))
{
vim_free(var);
var = NULL;
}
}
#ifdef HAVE_PATHDEF
/* for Unix we can use default_vim_dir */
if (var == NULL)
{
var = default_vim_dir;
mustfree = FALSE;
}
#endif
}
}
}
/* home directory */
else if ( src[1] == NUL
|| vim_ispathsep(src[1])
|| vim_strchr((char_u *)" ,\t\n", src[1]) != NULL)
{
var = homedir;
tail = src + 1;
}
else /* user directory */
{
#ifndef UNIX
/* cannot expand user's home directory, so don't try */
var = NULL;
tail = (char_u *)""; /* for gcc */
#else
/*
* Copy ~user to dst[], so we can put a NUL after it.
*/
tail = src;
var = dst;
c = dstlen - 1;
while ( c-- > 0
&& *tail
&& vim_isfilec(*tail)
&& !vim_ispathsep(*tail))
*var++ = *tail++;
*var = NUL;
/*
* If the system supports getpwnam(), use it.
* Otherwise, or if getpwnam() fails, the shell is used to
* expand ~user. This is slower and may fail if the shell
* does not support ~user (old versions of /bin/sh).
*/
# if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
{
struct passwd *pw;
pw = getpwnam((char *)dst + 1);
if (pw != NULL)
var = (char_u *)pw->pw_dir;
else
var = NULL;
}
if (var == NULL)
# endif
{
var = ExpandOne(dst, NULL, 0, WILD_EXPAND_FREE);
mustfree = TRUE;
}
#endif /* UNIX */
}
if (var != NULL && *var != NUL &&
(STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
{
STRCPY(dst, var);
dstlen -= STRLEN(var);
dst += STRLEN(var);
/* if var[] ends in a path separator and tail[] starts
* with it, skip a character */
if (*var && vim_ispathsep(*(dst-1)) && vim_ispathsep(*tail))
++tail;
src = tail;
copy_char = FALSE;
}
if (mustfree)
vim_free(var);
}
if (copy_char) /* copy at least one char */
{
/*
* Recogize the start of a new name, for '~'.
*/
at_start = FALSE;
if (src[0] == '\\')
{
*dst++ = *src++;
--dstlen;
}
else if (src[0] == ' ' || src[0] == ',')
at_start = TRUE;
*dst++ = *src++;
--dstlen;
}
}
*dst = NUL;
}
/*
* Call expand_env() and store the result in an allocated string.
* This is not very memory efficient, this expects the result to be freed
* again soon.
*/
char_u *
expand_env_save(src)
char_u *src;
{
char_u *p;
p = alloc(MAXPATHL);
if (p != NULL)
expand_env(src, p, MAXPATHL);
return p;
}
/*
* Replace home directory by "~" in each space or comma separated file name in
* 'src'.
* if "one" is TRUE, only replace one file name, include spaces and commas in
* the file name.
* If anything fails (except when out of space) dst equals src.
*/
void
home_replace(buf, src, dst, dstlen, one)
BUF *buf; /* when not NULL, check for help files */
char_u *src; /* input file name */
char_u *dst; /* where to put the result */
int dstlen; /* maximum length of the result */
int one;
{
size_t dirlen = 0, envlen = 0;
size_t len;
char_u *homedir_env;
char_u *p;
if (src == NULL)
{
*dst = NUL;
return;
}
/*
* If the file is a help file, remove the path completely.
*/
if (buf != NULL && buf->b_help)
{
STRCPY(dst, gettail(src));
return;
}
/*
* We check both the value of the $HOME environment variable and the
* "real" home directory.
*/
if (homedir != NULL)
dirlen = STRLEN(homedir);
homedir_env = mch_getenv((char_u *)"HOME");
if (homedir_env != NULL)
envlen = STRLEN(homedir_env);
if (!one)
src = skipwhite(src);
while (*src && dstlen > 0)
{
/*
* Here we are at the beginning of a file name.
* First, check to see if the beginning of the file name matches
* $HOME or the "real" home directory. Check that there is a '/'
* after the match (so that if e.g. the file is "/home/pieter/bla",
* and the home directory is "/home/piet", the file does not end up
* as "~er/bla" (which would seem to indicate the file "bla" in user
* er's home directory)).
*/
p = homedir;
len = dirlen;
for (;;)
{
if ( len
&& fnamencmp(src, p, len) == 0
&& (vim_ispathsep(src[len])
|| (!one && (src[len] == ',' || src[len] == ' '))
|| src[len] == NUL))
{
src += len;
if (--dstlen > 0)
*dst++ = '~';
/*
* If it's just the home directory, add "/".
*/
if (!vim_ispathsep(src[0]) && --dstlen > 0)
*dst++ = '/';
}
if (p == homedir_env)
break;
p = homedir_env;
len = envlen;
}
/* if (!one) skip to separator: space or comma */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -