mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
terminal.c: factor out the graphic-character display.
I'm about to want to implement an escape sequence that causes a graphic character to be printed, which means I'll need the code that does so to be in a separate routine that I can call easily, instead of buried a few loops deep in the middle of the main state machine.
This commit is contained in:
parent
6893f00e42
commit
a51dbf3f08
280
terminal.c
280
terminal.c
@ -2827,6 +2827,143 @@ static void term_print_finish(Terminal *term)
|
|||||||
term->printing = term->only_printing = FALSE;
|
term->printing = term->only_printing = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void term_display_graphic_char(Terminal *term, unsigned long c)
|
||||||
|
{
|
||||||
|
termline *cline = scrlineptr(term->curs.y);
|
||||||
|
int width = 0;
|
||||||
|
if (DIRECT_CHAR(c))
|
||||||
|
width = 1;
|
||||||
|
if (!width)
|
||||||
|
width = (term->cjk_ambig_wide ?
|
||||||
|
mk_wcwidth_cjk((unsigned int) c) :
|
||||||
|
mk_wcwidth((unsigned int) c));
|
||||||
|
|
||||||
|
if (term->wrapnext && term->wrap && width > 0) {
|
||||||
|
cline->lattr |= 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;
|
||||||
|
term->wrapnext = FALSE;
|
||||||
|
cline = scrlineptr(term->curs.y);
|
||||||
|
}
|
||||||
|
if (term->insert && width > 0)
|
||||||
|
insch(term, width);
|
||||||
|
if (term->selstate != NO_SELECTION) {
|
||||||
|
pos cursplus = term->curs;
|
||||||
|
incpos(cursplus);
|
||||||
|
check_selection(term, term->curs, cursplus);
|
||||||
|
}
|
||||||
|
if (((c & CSET_MASK) == CSET_ASCII ||
|
||||||
|
(c & CSET_MASK) == 0) && term->logctx)
|
||||||
|
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
copy_termchar(cline, term->curs.x,
|
||||||
|
&term->erase_char);
|
||||||
|
cline->lattr |= 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;
|
||||||
|
cline = scrlineptr(term->curs.y);
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FULL-TERMCHAR */
|
||||||
|
clear_cc(cline, term->curs.x);
|
||||||
|
cline->chars[term->curs.x].chr = c;
|
||||||
|
cline->chars[term->curs.x].attr = term->curr_attr;
|
||||||
|
cline->chars[term->curs.x].truecolour =
|
||||||
|
term->curr_truecolour;
|
||||||
|
|
||||||
|
term->curs.x++;
|
||||||
|
|
||||||
|
/* FULL-TERMCHAR */
|
||||||
|
clear_cc(cline, term->curs.x);
|
||||||
|
cline->chars[term->curs.x].chr = UCSWIDE;
|
||||||
|
cline->chars[term->curs.x].attr = term->curr_attr;
|
||||||
|
cline->chars[term->curs.x].truecolour =
|
||||||
|
term->curr_truecolour;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
check_boundary(term, term->curs.x, term->curs.y);
|
||||||
|
check_boundary(term, term->curs.x+1, term->curs.y);
|
||||||
|
|
||||||
|
/* FULL-TERMCHAR */
|
||||||
|
clear_cc(cline, term->curs.x);
|
||||||
|
cline->chars[term->curs.x].chr = c;
|
||||||
|
cline->chars[term->curs.x].attr = term->curr_attr;
|
||||||
|
cline->chars[term->curs.x].truecolour =
|
||||||
|
term->curr_truecolour;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
if (term->curs.x > 0) {
|
||||||
|
int x = term->curs.x - 1;
|
||||||
|
|
||||||
|
/* If we're in wrapnext state, the character to combine
|
||||||
|
* with is _here_, not to our left. */
|
||||||
|
if (term->wrapnext)
|
||||||
|
x++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the previous character is UCSWIDE, back up another
|
||||||
|
* one.
|
||||||
|
*/
|
||||||
|
if (cline->chars[x].chr == UCSWIDE) {
|
||||||
|
assert(x > 0);
|
||||||
|
x--;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_cc(cline, x, c);
|
||||||
|
seen_disp_event(term);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
term->curs.x++;
|
||||||
|
if (term->curs.x == term->cols) {
|
||||||
|
term->curs.x--;
|
||||||
|
term->wrapnext = TRUE;
|
||||||
|
if (term->wrap && term->vt52_mode) {
|
||||||
|
cline->lattr |= 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;
|
||||||
|
term->wrapnext = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seen_disp_event(term);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove everything currently in `inbuf' and stick it up on the
|
* Remove everything currently in `inbuf' and stick it up on the
|
||||||
* in-memory display. There's a big state machine in here to
|
* in-memory display. There's a big state machine in here to
|
||||||
@ -3241,148 +3378,7 @@ static void term_out(Terminal *term)
|
|||||||
case TOPLEVEL:
|
case TOPLEVEL:
|
||||||
/* Only graphic characters get this far;
|
/* Only graphic characters get this far;
|
||||||
* ctrls are stripped above */
|
* ctrls are stripped above */
|
||||||
{
|
term_display_graphic_char(term, c);
|
||||||
termline *cline = scrlineptr(term->curs.y);
|
|
||||||
int width = 0;
|
|
||||||
if (DIRECT_CHAR(c))
|
|
||||||
width = 1;
|
|
||||||
if (!width)
|
|
||||||
width = (term->cjk_ambig_wide ?
|
|
||||||
mk_wcwidth_cjk((unsigned int) c) :
|
|
||||||
mk_wcwidth((unsigned int) c));
|
|
||||||
|
|
||||||
if (term->wrapnext && term->wrap && width > 0) {
|
|
||||||
cline->lattr |= 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;
|
|
||||||
term->wrapnext = FALSE;
|
|
||||||
cline = scrlineptr(term->curs.y);
|
|
||||||
}
|
|
||||||
if (term->insert && width > 0)
|
|
||||||
insch(term, width);
|
|
||||||
if (term->selstate != NO_SELECTION) {
|
|
||||||
pos cursplus = term->curs;
|
|
||||||
incpos(cursplus);
|
|
||||||
check_selection(term, term->curs, cursplus);
|
|
||||||
}
|
|
||||||
if (((c & CSET_MASK) == CSET_ASCII ||
|
|
||||||
(c & CSET_MASK) == 0) &&
|
|
||||||
term->logctx)
|
|
||||||
logtraffic(term->logctx, (unsigned char) c,
|
|
||||||
LGTYP_ASCII);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
copy_termchar(cline, term->curs.x,
|
|
||||||
&term->erase_char);
|
|
||||||
cline->lattr |= 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;
|
|
||||||
cline = scrlineptr(term->curs.y);
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FULL-TERMCHAR */
|
|
||||||
clear_cc(cline, term->curs.x);
|
|
||||||
cline->chars[term->curs.x].chr = c;
|
|
||||||
cline->chars[term->curs.x].attr = term->curr_attr;
|
|
||||||
cline->chars[term->curs.x].truecolour =
|
|
||||||
term->curr_truecolour;
|
|
||||||
|
|
||||||
term->curs.x++;
|
|
||||||
|
|
||||||
/* FULL-TERMCHAR */
|
|
||||||
clear_cc(cline, term->curs.x);
|
|
||||||
cline->chars[term->curs.x].chr = UCSWIDE;
|
|
||||||
cline->chars[term->curs.x].attr = term->curr_attr;
|
|
||||||
cline->chars[term->curs.x].truecolour =
|
|
||||||
term->curr_truecolour;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
check_boundary(term, term->curs.x, term->curs.y);
|
|
||||||
check_boundary(term, term->curs.x+1, term->curs.y);
|
|
||||||
|
|
||||||
/* FULL-TERMCHAR */
|
|
||||||
clear_cc(cline, term->curs.x);
|
|
||||||
cline->chars[term->curs.x].chr = c;
|
|
||||||
cline->chars[term->curs.x].attr = term->curr_attr;
|
|
||||||
cline->chars[term->curs.x].truecolour =
|
|
||||||
term->curr_truecolour;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
if (term->curs.x > 0) {
|
|
||||||
int x = term->curs.x - 1;
|
|
||||||
|
|
||||||
/* If we're in wrapnext state, the character
|
|
||||||
* to combine with is _here_, not to our left. */
|
|
||||||
if (term->wrapnext)
|
|
||||||
x++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the previous character is
|
|
||||||
* UCSWIDE, back up another one.
|
|
||||||
*/
|
|
||||||
if (cline->chars[x].chr == UCSWIDE) {
|
|
||||||
assert(x > 0);
|
|
||||||
x--;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_cc(cline, x, c);
|
|
||||||
seen_disp_event(term);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
term->curs.x++;
|
|
||||||
if (term->curs.x == term->cols) {
|
|
||||||
term->curs.x--;
|
|
||||||
term->wrapnext = TRUE;
|
|
||||||
if (term->wrap && term->vt52_mode) {
|
|
||||||
cline->lattr |= 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;
|
|
||||||
term->wrapnext = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
seen_disp_event(term);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSC_MAYBE_ST:
|
case OSC_MAYBE_ST:
|
||||||
|
Loading…
Reference in New Issue
Block a user