mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +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;
|
||||
}
|
||||
|
||||
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
|
||||
* in-memory display. There's a big state machine in here to
|
||||
@ -3241,148 +3378,7 @@ static void term_out(Terminal *term)
|
||||
case TOPLEVEL:
|
||||
/* Only graphic characters get this far;
|
||||
* ctrls are stripped above */
|
||||
{
|
||||
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);
|
||||
}
|
||||
term_display_graphic_char(term, c);
|
||||
break;
|
||||
|
||||
case OSC_MAYBE_ST:
|
||||
|
Loading…
Reference in New Issue
Block a user