mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
I _think_ I've just fixed `font-overflow'. term->disptext now tracks
the start of every contiguous run passed to do_text() or do_cursor(), and arranges never to overwrite only part of such a run on the next update. I'm a bit worried about this checkin because I've also completely revamped cursor handling: the cursor was previously being drawn _outside_ the main loop over the display line, and is now drawn as part of that loop when it gets to the cursor location. It _seems_ to still work sensibly, even in complex cases involving LATTR_WIDE and double-width CJK characters etc, but I won't be entirely happy until it's had some beta use. [originally from svn r5003] [this svn revision also touched putty-wishlist]
This commit is contained in:
parent
cf44c428e3
commit
ba470dec5e
13
putty.h
13
putty.h
@ -36,6 +36,11 @@ typedef struct terminal_tag Terminal;
|
|||||||
*
|
*
|
||||||
* The LATTRs (line attributes) are an entirely disjoint space of
|
* The LATTRs (line attributes) are an entirely disjoint space of
|
||||||
* flags.
|
* flags.
|
||||||
|
*
|
||||||
|
* The DATTRs (display attributes) are internal to terminal.c (but
|
||||||
|
* defined here because their values have to match the others
|
||||||
|
* here); they reuse the TATTR_* space but are always masked off
|
||||||
|
* before sending to the front end.
|
||||||
*
|
*
|
||||||
* ATTR_INVALID is an illegal colour combination.
|
* ATTR_INVALID is an illegal colour combination.
|
||||||
*/
|
*/
|
||||||
@ -45,6 +50,12 @@ typedef struct terminal_tag Terminal;
|
|||||||
#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */
|
#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */
|
||||||
#define TATTR_COMBINING 0x80000000UL /* combining characters */
|
#define TATTR_COMBINING 0x80000000UL /* combining characters */
|
||||||
|
|
||||||
|
#define DATTR_STARTRUN 0x80000000UL /* start of redraw run */
|
||||||
|
|
||||||
|
#define TDATTR_MASK 0xF0000000UL
|
||||||
|
#define TATTR_MASK (TDATTR_MASK)
|
||||||
|
#define DATTR_MASK (TDATTR_MASK)
|
||||||
|
|
||||||
#define LATTR_NORM 0x00000000UL
|
#define LATTR_NORM 0x00000000UL
|
||||||
#define LATTR_WIDE 0x00000001UL
|
#define LATTR_WIDE 0x00000001UL
|
||||||
#define LATTR_TOP 0x00000002UL
|
#define LATTR_TOP 0x00000002UL
|
||||||
@ -53,7 +64,7 @@ typedef struct terminal_tag Terminal;
|
|||||||
#define LATTR_WRAPPED 0x00000010UL
|
#define LATTR_WRAPPED 0x00000010UL
|
||||||
#define LATTR_WRAPPED2 0x00000020UL
|
#define LATTR_WRAPPED2 0x00000020UL
|
||||||
|
|
||||||
#define ATTR_INVALID 0x03FFU
|
#define ATTR_INVALID 0x03FFFFU
|
||||||
|
|
||||||
/* Like Linux use the F000 page for direct to font. */
|
/* Like Linux use the F000 page for direct to font. */
|
||||||
#define CSET_OEMCP 0x0000F000UL /* OEM Codepage DTF */
|
#define CSET_OEMCP 0x0000F000UL /* OEM Codepage DTF */
|
||||||
|
115
terminal.c
115
terminal.c
@ -271,7 +271,7 @@ static int termchars_equal_override(termchar *a, termchar *b,
|
|||||||
/* FULL-TERMCHAR */
|
/* FULL-TERMCHAR */
|
||||||
if (a->chr != bchr)
|
if (a->chr != bchr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (a->attr != battr)
|
if ((a->attr &~ DATTR_MASK) != (battr &~ DATTR_MASK))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
while (a->cc_next || b->cc_next) {
|
while (a->cc_next || b->cc_next) {
|
||||||
if (!a->cc_next || !b->cc_next)
|
if (!a->cc_next || !b->cc_next)
|
||||||
@ -4539,14 +4539,11 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
pos scrpos;
|
pos scrpos;
|
||||||
wchar_t *ch;
|
wchar_t *ch;
|
||||||
int chlen;
|
int chlen;
|
||||||
termchar cursor_background;
|
|
||||||
#ifdef OPTIMISE_SCROLL
|
#ifdef OPTIMISE_SCROLL
|
||||||
struct scrollregion *sr;
|
struct scrollregion *sr;
|
||||||
#endif /* OPTIMISE_SCROLL */
|
#endif /* OPTIMISE_SCROLL */
|
||||||
termchar *newline;
|
termchar *newline;
|
||||||
|
|
||||||
cursor_background = term->basic_erase_char;
|
|
||||||
|
|
||||||
chlen = 1024;
|
chlen = 1024;
|
||||||
ch = snewn(chlen, wchar_t);
|
ch = snewn(chlen, wchar_t);
|
||||||
|
|
||||||
@ -4646,6 +4643,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
int start = 0;
|
int start = 0;
|
||||||
int ccount = 0;
|
int ccount = 0;
|
||||||
int last_run_dirty = 0;
|
int last_run_dirty = 0;
|
||||||
|
int laststart, dirtyrect;
|
||||||
int *backward;
|
int *backward;
|
||||||
|
|
||||||
scrpos.y = i + term->disptop;
|
scrpos.y = i + term->disptop;
|
||||||
@ -4727,22 +4725,15 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
*/
|
*/
|
||||||
if (tchar != term->disptext[i]->chars[j].chr ||
|
if (tchar != term->disptext[i]->chars[j].chr ||
|
||||||
tattr != (term->disptext[i]->chars[j].attr &~
|
tattr != (term->disptext[i]->chars[j].attr &~
|
||||||
ATTR_NARROW)) {
|
(ATTR_NARROW | DATTR_MASK))) {
|
||||||
if ((tattr & ATTR_WIDE) == 0 && char_width(ctx, tchar) == 2)
|
if ((tattr & ATTR_WIDE) == 0 && char_width(ctx, tchar) == 2)
|
||||||
tattr |= ATTR_NARROW;
|
tattr |= ATTR_NARROW;
|
||||||
} else if (term->disptext[i]->chars[j].attr & ATTR_NARROW)
|
} else if (term->disptext[i]->chars[j].attr & ATTR_NARROW)
|
||||||
tattr |= ATTR_NARROW;
|
tattr |= ATTR_NARROW;
|
||||||
|
|
||||||
/* Cursor here ? Save the 'background' */
|
|
||||||
if (i == our_curs_y && j == our_curs_x) {
|
if (i == our_curs_y && j == our_curs_x) {
|
||||||
/* FULL-TERMCHAR */
|
tattr |= cursor;
|
||||||
cursor_background.chr = tchar;
|
term->curstype = cursor;
|
||||||
cursor_background.attr = tattr;
|
|
||||||
/* For once, this cc_next field is an absolute index in lchars */
|
|
||||||
if (d->cc_next)
|
|
||||||
cursor_background.cc_next = d->cc_next + j;
|
|
||||||
else
|
|
||||||
cursor_background.cc_next = 0;
|
|
||||||
term->dispcursx = j;
|
term->dispcursx = j;
|
||||||
term->dispcursy = i;
|
term->dispcursy = i;
|
||||||
}
|
}
|
||||||
@ -4757,12 +4748,38 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
/*
|
/*
|
||||||
* Now loop over the line again, noting where things have
|
* Now loop over the line again, noting where things have
|
||||||
* changed.
|
* changed.
|
||||||
|
*
|
||||||
|
* During this loop, we keep track of where we last saw
|
||||||
|
* DATTR_STARTRUN. Any mismatch automatically invalidates
|
||||||
|
* _all_ of the containing run that was last printed: that
|
||||||
|
* is, any rectangle that was drawn in one go in the
|
||||||
|
* previous update should be either left completely alone
|
||||||
|
* or overwritten in its entirety. This, along with the
|
||||||
|
* expectation that front ends clip all text runs to their
|
||||||
|
* bounding rectangle, should solve any possible problems
|
||||||
|
* with fonts that overflow their character cells.
|
||||||
*/
|
*/
|
||||||
|
laststart = 0;
|
||||||
|
dirtyrect = FALSE;
|
||||||
for (j = 0; j < term->cols; j++) {
|
for (j = 0; j < term->cols; j++) {
|
||||||
if (term->disptext[i]->chars[j].chr != newline[j].chr ||
|
if (term->disptext[i]->chars[j].attr & DATTR_STARTRUN) {
|
||||||
term->disptext[i]->chars[j].attr != newline[j].attr) {
|
laststart = j;
|
||||||
term->disptext[i]->chars[j].attr |= ATTR_INVALID;
|
dirtyrect = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (term->disptext[i]->chars[j].chr != newline[j].chr ||
|
||||||
|
(term->disptext[i]->chars[j].attr &~ DATTR_MASK)
|
||||||
|
!= newline[j].attr) {
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (k = laststart; k < j; k++)
|
||||||
|
term->disptext[i]->chars[k].attr |= ATTR_INVALID;
|
||||||
|
|
||||||
|
dirtyrect = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirtyrect)
|
||||||
|
term->disptext[i]->chars[j].attr |= ATTR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4805,7 +4822,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
|
|
||||||
if (!term->ucsdata->dbcs_screenfont && !dirty_line) {
|
if (!term->ucsdata->dbcs_screenfont && !dirty_line) {
|
||||||
if (term->disptext[i]->chars[j].chr == tchar &&
|
if (term->disptext[i]->chars[j].chr == tchar &&
|
||||||
term->disptext[i]->chars[j].attr == tattr)
|
(term->disptext[i]->chars[j].attr &~ DATTR_MASK) == tattr)
|
||||||
break_run = TRUE;
|
break_run = TRUE;
|
||||||
else if (!dirty_run && ccount == 1)
|
else if (!dirty_run && ccount == 1)
|
||||||
break_run = TRUE;
|
break_run = TRUE;
|
||||||
@ -4813,7 +4830,13 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
|
|
||||||
if (break_run) {
|
if (break_run) {
|
||||||
if ((dirty_run || last_run_dirty) && ccount > 0) {
|
if ((dirty_run || last_run_dirty) && ccount > 0) {
|
||||||
do_text(ctx, start, i, ch, ccount, attr, ldata->lattr);
|
if (attr & (TATTR_ACTCURS | TATTR_PASCURS))
|
||||||
|
do_cursor(ctx, our_curs_x, i, ch, ccount, attr,
|
||||||
|
ldata->lattr);
|
||||||
|
else
|
||||||
|
do_text(ctx, start, i, ch, ccount, attr,
|
||||||
|
ldata->lattr);
|
||||||
|
|
||||||
updated_line = 1;
|
updated_line = 1;
|
||||||
}
|
}
|
||||||
start = j;
|
start = j;
|
||||||
@ -4873,6 +4896,8 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
copy_termchar(term->disptext[i], j, d);
|
copy_termchar(term->disptext[i], j, d);
|
||||||
term->disptext[i]->chars[j].chr = tchar;
|
term->disptext[i]->chars[j].chr = tchar;
|
||||||
term->disptext[i]->chars[j].attr = tattr;
|
term->disptext[i]->chars[j].attr = tattr;
|
||||||
|
if (start == j)
|
||||||
|
term->disptext[i]->chars[j].attr |= DATTR_STARTRUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it's a wide char step along to the next one. */
|
/* If it's a wide char step along to the next one. */
|
||||||
@ -4892,54 +4917,16 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dirty_run && ccount > 0) {
|
if (dirty_run && ccount > 0) {
|
||||||
do_text(ctx, start, i, ch, ccount, attr, ldata->lattr);
|
if (attr & (TATTR_ACTCURS | TATTR_PASCURS))
|
||||||
|
do_cursor(ctx, our_curs_x, i, ch, ccount, attr,
|
||||||
|
ldata->lattr);
|
||||||
|
else
|
||||||
|
do_text(ctx, start, i, ch, ccount, attr,
|
||||||
|
ldata->lattr);
|
||||||
|
|
||||||
updated_line = 1;
|
updated_line = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cursor on this line ? (and changed) */
|
|
||||||
if (i == our_curs_y && (term->curstype != cursor || updated_line)) {
|
|
||||||
ch[0] = (wchar_t) cursor_background.chr;
|
|
||||||
attr = cursor_background.attr | cursor;
|
|
||||||
ccount = 1;
|
|
||||||
|
|
||||||
if (cursor_background.cc_next) {
|
|
||||||
termchar *dd = ldata->chars + cursor_background.cc_next;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
unsigned long schar;
|
|
||||||
|
|
||||||
schar = dd->chr;
|
|
||||||
switch (schar & CSET_MASK) {
|
|
||||||
case CSET_ASCII:
|
|
||||||
schar = term->ucsdata->unitab_line[schar & 0xFF];
|
|
||||||
break;
|
|
||||||
case CSET_LINEDRW:
|
|
||||||
schar = term->ucsdata->unitab_xterm[schar & 0xFF];
|
|
||||||
break;
|
|
||||||
case CSET_SCOACS:
|
|
||||||
schar = term->ucsdata->unitab_scoacs[schar&0xFF];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ccount >= chlen) {
|
|
||||||
chlen = ccount + 256;
|
|
||||||
ch = sresize(ch, chlen, wchar_t);
|
|
||||||
}
|
|
||||||
ch[ccount++] = (wchar_t) schar;
|
|
||||||
|
|
||||||
if (dd->cc_next)
|
|
||||||
dd += dd->cc_next;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
attr |= TATTR_COMBINING;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_cursor(ctx, our_curs_x, i, ch, ccount, attr, ldata->lattr);
|
|
||||||
term->curstype = cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlineptr(ldata);
|
unlineptr(ldata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user