📄 terminal.c
字号:
term->esc_query = FALSE;
}
break;
case '\015': /* CR: Carriage return */
term->curs.x = 0;
term->wrapnext = FALSE;
fix_cpos;
term->seen_disp_event = TRUE;
term->paste_hold = 0;
if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break;
case '\014': /* FF: Form feed */
if (has_compat(SCOANSI)) {
move(term, 0, 0, 0);
erase_lots(term, FALSE, FALSE, TRUE);
term->disptop = 0;
term->wrapnext = FALSE;
term->seen_disp_event = 1;
break;
}
case '\013': /* VT: Line tabulation */
compatibility(VT100);
case '\012': /* LF: Line feed */
if (term->curs.y == term->marg_b)
scroll(term, term->marg_t, term->marg_b, 1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
if (term->cfg.lfhascr)
term->curs.x = 0;
fix_cpos;
term->wrapnext = FALSE;
term->seen_disp_event = 1;
term->paste_hold = 0;
if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break;
case '\t': /* HT: Character tabulation */
{
pos old_curs = term->curs;
unsigned long *ldata = lineptr(term->curs.y);
do {
term->curs.x++;
} while (term->curs.x < term->cols - 1 &&
!term->tabs[term->curs.x]);
if ((ldata[term->cols] & LATTR_MODE) != LATTR_NORM) {
if (term->curs.x >= term->cols / 2)
term->curs.x = term->cols / 2 - 1;
} else {
if (term->curs.x >= term->cols)
term->curs.x = term->cols - 1;
}
fix_cpos;
check_selection(term, old_curs, term->curs);
}
term->seen_disp_event = TRUE;
break;
}
} else
switch (term->termstate) {
case TOPLEVEL:
/* Only graphic characters get this far;
* ctrls are stripped above */
if (term->wrapnext && term->wrap) {
term->cpos[1] |= LATTR_WRAPPED;
if (term->curs.y == term->marg_b)
scroll(term, term->marg_t, term->marg_b, 1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
term->curs.x = 0;
fix_cpos;
term->wrapnext = FALSE;
}
if (term->insert)
insch(term, 1);
if (term->selstate != NO_SELECTION) {
pos cursplus = term->curs;
incpos(cursplus);
check_selection(term, term->curs, cursplus);
}
if (((c & CSET_MASK) == ATTR_ASCII || (c & CSET_MASK) == 0) &&
term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
{
int width = 0;
if (DIRECT_CHAR(c))
width = 1;
if (!width)
width = wcwidth((wchar_t) c);
switch (width) {
case 2:
/*
* If we're about to display a double-width
* character starting in the rightmost
* column, then we do something special
* instead. We must print a space in the
* last column of the screen, then wrap;
* and we also set LATTR_WRAPPED2 which
* instructs subsequent cut-and-pasting not
* only to splice this line to the one
* after it, but to ignore the space in the
* last character position as well.
* (Because what was actually output to the
* terminal was presumably just a sequence
* of CJK characters, and we don't want a
* space to be pasted in the middle of
* those just because they had the
* misfortune to start in the wrong parity
* column. xterm concurs.)
*/
check_boundary(term, term->curs.x, term->curs.y);
check_boundary(term, term->curs.x+2, term->curs.y);
if (term->curs.x == term->cols-1) {
*term->cpos++ = ATTR_ASCII | ' ' | term->curr_attr;
*term->cpos |= LATTR_WRAPPED | LATTR_WRAPPED2;
if (term->curs.y == term->marg_b)
scroll(term, term->marg_t, term->marg_b,
1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
term->curs.x = 0;
fix_cpos;
/* Now we must check_boundary again, of course. */
check_boundary(term, term->curs.x, term->curs.y);
check_boundary(term, term->curs.x+2, term->curs.y);
}
*term->cpos++ = c | term->curr_attr;
*term->cpos++ = UCSWIDE | term->curr_attr;
term->curs.x++;
break;
case 1:
check_boundary(term, term->curs.x, term->curs.y);
check_boundary(term, term->curs.x+1, term->curs.y);
*term->cpos++ = c | term->curr_attr;
break;
default:
continue;
}
}
term->curs.x++;
if (term->curs.x == term->cols) {
term->cpos--;
term->curs.x--;
term->wrapnext = TRUE;
if (term->wrap && term->vt52_mode) {
term->cpos[1] |= LATTR_WRAPPED;
if (term->curs.y == term->marg_b)
scroll(term, term->marg_t, term->marg_b, 1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
term->curs.x = 0;
fix_cpos;
term->wrapnext = FALSE;
}
}
term->seen_disp_event = 1;
break;
case OSC_MAYBE_ST:
/*
* This state is virtually identical to SEEN_ESC, with the
* exception that we have an OSC sequence in the pipeline,
* and _if_ we see a backslash, we process it.
*/
if (c == '\\') {
do_osc(term);
term->termstate = TOPLEVEL;
break;
}
/* else fall through */
case SEEN_ESC:
if (c >= ' ' && c <= '/') {
if (term->esc_query)
term->esc_query = -1;
else
term->esc_query = c;
break;
}
term->termstate = TOPLEVEL;
switch (ANSI(c, term->esc_query)) {
case '[': /* enter CSI mode */
term->termstate = SEEN_CSI;
term->esc_nargs = 1;
term->esc_args[0] = ARG_DEFAULT;
term->esc_query = FALSE;
break;
case ']': /* OSC: xterm escape sequences */
/* Compatibility is nasty here, xterm, linux, decterm yuk! */
compatibility(OTHER);
term->termstate = SEEN_OSC;
term->esc_args[0] = 0;
break;
case '7': /* DECSC: save cursor */
compatibility(VT100);
save_cursor(term, TRUE);
break;
case '8': /* DECRC: restore cursor */
compatibility(VT100);
save_cursor(term, FALSE);
term->seen_disp_event = TRUE;
break;
case '=': /* DECKPAM: Keypad application mode */
compatibility(VT100);
term->app_keypad_keys = TRUE;
break;
case '>': /* DECKPNM: Keypad numeric mode */
compatibility(VT100);
term->app_keypad_keys = FALSE;
break;
case 'D': /* IND: exactly equivalent to LF */
compatibility(VT100);
if (term->curs.y == term->marg_b)
scroll(term, term->marg_t, term->marg_b, 1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
fix_cpos;
term->wrapnext = FALSE;
term->seen_disp_event = TRUE;
break;
case 'E': /* NEL: exactly equivalent to CR-LF */
compatibility(VT100);
term->curs.x = 0;
if (term->curs.y == term->marg_b)
scroll(term, term->marg_t, term->marg_b, 1, TRUE);
else if (term->curs.y < term->rows - 1)
term->curs.y++;
fix_cpos;
term->wrapnext = FALSE;
term->seen_disp_event = TRUE;
break;
case 'M': /* RI: reverse index - backwards LF */
compatibility(VT100);
if (term->curs.y == term->marg_t)
scroll(term, term->marg_t, term->marg_b, -1, TRUE);
else if (term->curs.y > 0)
term->curs.y--;
fix_cpos;
term->wrapnext = FALSE;
term->seen_disp_event = TRUE;
break;
case 'Z': /* DECID: terminal type query */
compatibility(VT100);
if (term->ldisc)
ldisc_send(term->ldisc, term->id_string,
strlen(term->id_string), 0);
break;
case 'c': /* RIS: restore power-on settings */
compatibility(VT100);
power_on(term);
if (term->ldisc) /* cause ldisc to notice changes */
ldisc_send(term->ldisc, NULL, 0, 0);
if (term->reset_132) {
if (!term->cfg.no_remote_resize)
request_resize(term->frontend, 80, term->rows);
term->reset_132 = 0;
}
fix_cpos;
term->disptop = 0;
term->seen_disp_event = TRUE;
break;
case 'H': /* HTS: set a tab */
compatibility(VT100);
term->tabs[term->curs.x] = TRUE;
break;
case ANSI('8', '#'): /* DECALN: fills screen with Es :-) */
compatibility(VT100);
{
unsigned long *ldata;
int i, j;
pos scrtop, scrbot;
for (i = 0; i < term->rows; i++) {
ldata = lineptr(i);
for (j = 0; j < term->cols; j++)
ldata[j] = ATTR_DEFAULT | 'E';
ldata[term->cols] = 0;
}
term->disptop = 0;
term->seen_disp_event = TRUE;
scrtop.x = scrtop.y = 0;
scrbot.x = 0;
scrbot.y = term->rows;
check_selection(term, scrtop, scrbot);
}
break;
case ANSI('3', '#'):
case ANSI('4', '#'):
case ANSI('5', '#'):
case ANSI('6', '#'):
compatibility(VT100);
{
unsigned long nlattr;
unsigned long *ldata;
switch (ANSI(c, term->esc_query)) {
case ANSI('3', '#'): /* DECDHL: 2*height, top */
nlattr = LATTR_TOP;
break;
case ANSI('4', '#'): /* DECDHL: 2*height, bottom */
nlattr = LATTR_BOT;
break;
case ANSI('5', '#'): /* DECSWL: normal */
nlattr = LATTR_NORM;
break;
default: /* case ANSI('6', '#'): DECDWL: 2*width */
nlattr = LATTR_WIDE;
break;
}
ldata = lineptr(term->curs.y);
ldata[term->cols] &= ~LATTR_MODE;
ldata[term->cols] |= nlattr;
}
break;
/* GZD4: G0 designate 94-set */
case ANSI('A', '('):
compatibility(VT100);
if (!term->cfg.no_remote_charset)
term->cset_attr[0] = ATTR_GBCHR;
break;
case ANSI('B', '('):
compatibility(VT100);
if (!term->cfg.no_remote_charset)
term->cset_attr[0] = ATTR_ASCII;
break;
case ANSI('0', '('):
compatibility(VT100);
if (!term->cfg.no_remote_charset)
term->cset_attr[0] = ATTR_LINEDRW;
break;
case ANSI('U', '('):
compatibility(OTHER);
if (!term->cfg.no_remote_charset)
term->cset_attr[0] = ATTR_SCOACS;
break;
/* G1D4: G1-designate 94-set */
case ANSI('A', ')'):
compatibility(VT100);
if (!term->cfg.no_remote_charset)
term->cset_attr[1] = ATTR_GBCHR;
break;
case ANSI('B', ')'):
compatibility(VT100);
if (!term->cfg.no_remote_charset)
term->cset_attr[1] = ATTR_ASCII;
break;
case ANSI('0', ')'):
compatibility(VT100);
if (!term->cfg.no_remote_charset)
term->cset_attr[1] = ATTR_LINEDRW;
break;
case ANSI('U', ')'):
compatibility(OTHER);
if (!term->cfg.no_remote_charset)
term->cset_attr[1] = ATTR_SCOACS;
break;
/* DOCS: Designate other coding system */
case ANSI('8', '%'): /* Old Linux code */
case ANSI('G', '%'):
compatibility(OTHER);
if (!term->cfg.no_remote_charset)
term->utf = 1;
break;
case ANSI('@', '%'):
compatibility(OTHER);
if (!term->cfg.no_remote_charset)
term->utf = 0;
break;
}
break;
case SEEN_CSI:
term->termstate = TOPLEVEL; /* default */
if (isdigit(c)) {
if (term->esc_nargs <= ARGS_MAX) {
if (term->esc_args[term->esc_nargs - 1] == ARG_DEFAULT)
term->esc_args[term->esc_nargs - 1] = 0;
term->esc_args[term->esc_nargs - 1] =
10 * term->esc_args[term->esc_nargs - 1] + c - '0';
}
term->termstate = SEEN_CSI;
} else if (c == ';') {
if (++term->esc_nargs <= ARGS_MAX)
term->esc_args[term->esc_nargs - 1] = ARG_DEFAULT;
term->termstate = SEEN_CSI;
} else if (c < '@') {
if (term->esc_query)
term->esc_query = -1;
else if (c == '?')
term->esc_query = TRUE;
else
term->esc_query = c;
term->termstate = SEEN_CSI;
} else
switch (ANSI(c, term->esc_query)) {
case 'A': /* CUU: move up N lines */
move(term, term->curs.x,
term->curs.y - def(term->esc_args[0], 1), 1);
term->seen_disp_event = TRUE;
break;
case 'e': /* VPR: move down N lines */
compatibility(ANSI);
/* FALLTHROUGH */
case 'B': /* CUD: Cursor down */
move(term, term->curs.x,
term->curs.y + def(term->esc_args[0], 1), 1);
term->seen_disp_event = TRUE;
break;
case ANSI('c', '>'): /* DA: report xterm version */
compatibility(OTHER);
/* this reports xterm version 136 so that VIM can
use the drag messages from the mouse reporting */
if (term->ldisc)
ldisc_send(term->ldisc, "\033[>0;136;0c", 11, 0);
break;
case 'a': /* HPR: move right N cols */
compatibility(ANSI);
/* FALLTHROUGH */
case 'C': /* CUF: Cursor right */
move(term, term->curs.x + def(term->esc_args[0], 1),
term->curs.y, 1);
term->seen_disp_event = TRUE;
break;
case 'D': /* CUB: move left N cols */
move(term, term->curs.x - def(term->esc_args[0], 1),
term->curs.y, 1);
term->seen_disp_event = TRUE;
break;
case 'E':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -