📄 term.c
字号:
#endif /* USE_MOUSE */
#ifdef USE_SNIFF
{
char_u name[2];
name[0] = (int)KS_EXTRA;
name[1] = (int)KE_SNIFF;
add_termcode(name, (char_u *)"\233sniff");
}
#endif
#if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BEOS__) || defined(RISCOS)
/* DEFAULT_TERM indicates that it is the machine console. */
if (STRCMP(term, DEFAULT_TERM))
term_console = FALSE;
else
{
term_console = TRUE;
# ifdef AMIGA
win_resize_on(); /* enable window resizing reports */
# endif
}
#endif
#ifdef UNIX
/*
* 'ttyfast' is default on for xterm, iris-ansi and a few others.
*/
if (vim_is_fastterm(term))
p_tf = TRUE;
#endif
#if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BEOS__) || defined(RISCOS)
/*
* 'ttyfast' is default on Amiga, MSDOS, Win32, BeBox, RISCOS and OS/2 consoles
*/
if (term_console)
p_tf = TRUE;
#endif
ttest(TRUE); /* make sure we have a valid set of terminal codes */
full_screen = TRUE; /* we can use termcap codes from now on */
set_term_defaults(); /* use current values as defaults */
/*
* Initialize the terminal with the appropriate termcap codes.
* Set the mouse and window title if possible.
* Don't do this when starting, need to parse the .vimrc first, because it
* may redefine t_TI etc.
*/
if (!starting)
{
starttermcap(); /* may change terminal mode */
#ifdef USE_MOUSE
setmouse(); /* may start using the mouse */
#endif
maketitle(); /* may display window title */
}
/* display initial screen after ttest() checking. jw. */
if (width <= 0 || height <= 0)
{
/* termcap failed to report size */
/* set defaults, in case ui_get_winsize also fails */
width = 80;
#if defined MSDOS || defined WIN32
height = 25; /* console is often 25 lines */
#else
height = 24; /* most terminals are 24 lines */
#endif
}
set_winsize(width, height, FALSE); /* may change Rows */
if (!starting)
{
if (scroll_region)
scroll_region_reset(); /* In case Rows changed */
check_map_keycodes(); /* check mappings for terminal codes used */
#ifdef AUTOCMD
{
BUF *old_curbuf;
/*
* Execute the TermChanged autocommands for each buffer that is
* loaded.
*/
old_curbuf = curbuf;
for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
{
if (curbuf->b_ml.ml_mfp != NULL)
apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
curbuf);
}
if (buf_valid(old_curbuf))
curbuf = old_curbuf;
}
#endif
}
return OK;
}
#ifdef USE_MOUSE
void
set_mouse_termcode(n, s)
int n; /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
char_u *s;
{
char_u name[2];
name[0] = n;
name[1] = K_FILLER;
add_termcode(name, s);
}
# ifdef UNIX
void
del_mouse_termcode(n)
int n; /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
{
char_u name[2];
name[0] = n;
name[1] = K_FILLER;
del_termcode(name);
}
# endif
#endif /* USE_MOUSE */
#ifdef HAVE_TGETENT
/*
* Call tgetent()
* Return error message if it fails, NULL if it's OK.
*/
static char_u *
tgetent_error(tbuf, term)
char_u *tbuf;
char_u *term;
{
int i;
i = TGETENT(tbuf, term);
if (i == -1)
return (char_u *)"Cannot open termcap file";
if (i == 0)
#ifdef TERMINFO
return (char_u *)"Terminal entry not found in terminfo";
#else
return (char_u *)"Terminal entry not found in termcap";
#endif
return NULL;
}
#endif /* HAVE_TGETENT */
#if defined(HAVE_TGETENT) && (defined(UNIX) || defined(__EMX__))
/*
* Get Columns and Rows from the termcap. Used after a window signal if the
* ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
* and "li" entries never change. But on some systems this works.
* Errors while getting the entries are ignored.
*/
void
getlinecol()
{
char_u tbuf[TBUFSZ];
if (T_NAME != NULL && *T_NAME != NUL && TGETENT(tbuf, T_NAME) > 0)
{
if (Columns == 0)
Columns = tgetnum("co");
if (Rows == 0)
Rows = tgetnum("li");
}
}
#endif /* defined(HAVE_TGETENT) && defined(UNIX) */
/*
* Get a string entry from the termcap and add it to the list of termcodes.
* Used for <t_xx> special keys.
* Give an error message for failure when not sourcing.
* If force given, replace an existing entry.
* Return FAIL if the entry was not found, OK if the entry was added.
*/
int
add_termcap_entry(name, force)
char_u *name;
int force;
{
char_u *term;
int key;
struct builtin_term *termp;
#ifdef HAVE_TGETENT
char_u *string;
int i;
int builtin_first;
char_u tbuf[TBUFSZ];
char_u tstrbuf[TBUFSZ];
char_u *tp = tstrbuf;
char_u *error_msg = NULL;
#endif
/*
* If the GUI is running or will start in a moment, we only support the keys
* that the GUI can produce.
*/
#ifdef USE_GUI
if (gui.in_use || gui.starting)
return gui_mch_haskey(name);
#endif
if (!force && find_termcode(name) != NULL) /* it's already there */
return OK;
term = T_NAME;
if (term == NULL || *term == NUL) /* 'term' not defined yet */
return FAIL;
if (term_is_builtin(term)) /* name starts with "builtin_" */
{
term += 8;
#ifdef HAVE_TGETENT
builtin_first = TRUE;
#endif
}
#ifdef HAVE_TGETENT
else
builtin_first = p_tbi;
#endif
#ifdef HAVE_TGETENT
/*
* We can get the entry from the builtin termcap and from the external one.
* If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
* builtin termcap first.
* If 'ttybuiltin' is off, try external termcap first.
*/
for (i = 0; i < 2; ++i)
{
if (!builtin_first == i)
#endif
/*
* Search in builtin termcap
*/
{
termp = find_builtin_term(term);
if (termp->bt_string != NULL) /* found it */
{
key = TERMCAP2KEY(name[0], name[1]);
while (termp->bt_entry != (int)KS_NAME)
{
if ((int)termp->bt_entry == key)
{
add_termcode(name, (char_u *)termp->bt_string);
return OK;
}
++termp;
}
}
}
#ifdef HAVE_TGETENT
else
/*
* Search in external termcap
*/
{
error_msg = tgetent_error(tbuf, term);
if (error_msg == NULL)
{
string = TGETSTR((char *)name, &tp);
if (string != NULL && *string != NUL)
{
add_termcode(name, string);
return OK;
}
}
}
}
#endif
if (sourcing_name == NULL)
{
#ifdef HAVE_TGETENT
if (error_msg != NULL)
EMSG(error_msg);
else
#endif
EMSG2("No \"%s\" entry in termcap", name);
}
return FAIL;
}
static int
term_is_builtin(name)
char_u *name;
{
return (STRNCMP(name, "builtin_", (size_t)8) == 0);
}
#ifdef USE_GUI
int
term_is_gui(name)
char_u *name;
{
return (STRCMP(name, "builtin_gui") == 0 || STRCMP(name, "gui") == 0);
}
#endif
#if !defined(HAVE_TGETENT) || defined(AMIGA) || defined(PROTO)
char_u *
tltoa(i)
unsigned long i;
{
static char_u buf[16];
char_u *p;
p = buf + 15;
*p = '\0';
do
{
--p;
*p = (char_u) (i % 10 + '0');
i /= 10;
}
while (i > 0 && p > buf);
return p;
}
#endif
#ifndef HAVE_TGETENT
/*
* minimal tgoto() implementation.
* no padding and we only parse for %i %d and %+char
*/
char *tgoto __ARGS((char *, int, int));
char *
tgoto(cm, x, y)
char *cm;
int x, y;
{
static char buf[30];
char *p, *s, *e;
if (!cm)
return "OOPS";
e = buf + 29;
for (s = buf; s < e && *cm; cm++)
{
if (*cm != '%')
{
*s++ = *cm;
continue;
}
switch (*++cm)
{
case 'd':
p = (char *)tltoa((unsigned long)y);
y = x;
while (*p)
*s++ = *p++;
break;
case 'i':
x++;
y++;
break;
case '+':
*s++ = (char)(*++cm + y);
y = x;
break;
case '%':
*s++ = *cm;
break;
default:
return "OOPS";
}
}
*s = '\0';
return buf;
}
#endif /* HAVE_TGETENT */
/*
* Set the terminal name and initialize the terminal options.
* If "name" is NULL or empty, get the terminal name from the environment.
* If that fails, use the default terminal name.
*/
void
termcapinit(name)
char_u *name;
{
char_u *term;
if (name != NULL && *name == NUL)
name = NULL; /* empty name is equal to no name */
term = name;
#ifdef __BEOS__
/*
* TERM environment variable is normally set to 'ansi' on the Bebox;
* Since the BeBox doesn't quite support full ANSI yet, we use our
* own custom 'ansi-beos' termcap instead, unless the -T option has
* been given on the command line.
*/
if (term == NULL
&& strcmp((char *)mch_getenv((char_u *)"TERM"), "ansi") == 0)
term = DEFAULT_TERM;
#endif
#ifndef WIN32
if (term == NULL)
term = mch_getenv((char_u *)"TERM");
#endif
if (term == NULL || *term == NUL)
term = DEFAULT_TERM;
set_string_option_direct((char_u *)"term", -1, term, TRUE);
/* Set the default terminal name. */
set_string_default("term", term);
set_string_default("ttytype", term);
/*
* Avoid using "term" here, because the next mch_getenv() may overwrite it.
*/
set_termname(T_NAME != NULL ? T_NAME : term);
}
/*
* the number of calls to ui_write is reduced by using the buffer "out_buf"
*/
#ifdef DOS16
# define OUT_SIZE 255 /* only have 640K total... */
#else
# define OUT_SIZE 2047
#endif
/* Add one to allow mch_write() in os_win32.c to append a NUL */
static char_u out_buf[OUT_SIZE + 1];
static int out_pos = 0; /* number of chars in out_buf */
/*
* out_flush(): flush the output buffer
*/
void
out_flush()
{
int len;
if (out_pos != 0)
{
/* set out_pos to 0 before ui_write, to avoid recursiveness */
len = out_pos;
out_pos = 0;
ui_write(out_buf, len);
}
}
#ifdef USE_GUI
/*
* out_trash(): Throw away the contents of the output buffer
*/
void
out_trash()
{
out_pos = 0;
}
#endif
/*
* out_char(c): put a character into the output buffer.
* Flush it if it becomes full.
* This should not be used for outputting text on the screen (use functions
* like msg_puts() and screen_putchar() for that).
*/
void
out_char(c)
unsigned c;
{
#if defined(UNIX) || defined(VMS) || defined(AMIGA)
if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
out_char('\r');
#endif
out_buf[out_pos++] = c;
/* For testing we flush each time. */
if (out_pos >= OUT_SIZE || p_wd)
out_flush();
}
static void out_char_nf __ARGS((unsigned));
/*
* out_char_nf(c): like out_char(), but don't flush when p_wd is set
*/
static void
out_char_nf(c)
unsigned c;
{
#if defined(UNIX) || defined(VMS) || defined(AMIGA)
if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
out_char_nf('\r');
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -