1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Re-engineering of terminal emulator, phase 1.

The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.

To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.

Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.

Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.

As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.

[originally from svn r4609]
This commit is contained in:
Simon Tatham 2004-10-13 11:50:16 +00:00
parent f531e558f3
commit 709a94e5f2
7 changed files with 1041 additions and 487 deletions

View File

@ -1,4 +1,4 @@
/* $Id: macterm.c,v 1.76 2004/06/20 17:07:37 jacob Exp $ */
/* $Id: macterm.c,v 1.77 2004/10/13 11:50:16 simon Exp $ */
/*
* Copyright (c) 1999 Simon Tatham
* Copyright (c) 1999, 2002 Ben Harris
@ -1139,7 +1139,7 @@ struct do_text_args {
*
* x and y are text row and column (zero-based)
*/
void do_text(Context ctx, int x, int y, char *text, int len,
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
Session *s = ctx;
@ -1150,7 +1150,6 @@ void do_text(Context ctx, int x, int y, char *text, int len,
RgnHandle visrgn;
#endif
char mactextbuf[1024];
UniChar unitextbuf[1024];
wchar_t *unitextptr;
int i, fontwidth;
ByteCount iread, olen;
@ -1185,20 +1184,16 @@ void do_text(Context ctx, int x, int y, char *text, int len,
return;
#endif
/* Unpack Unicode from the mad format we get passed */
for (i = 0; i < len; i++)
unitextbuf[i] = (unsigned char)text[i] | (attr & CSET_MASK);
if (s->uni_to_font != NULL) {
err = ConvertFromUnicodeToText(s->uni_to_font, len * sizeof(UniChar),
unitextbuf, kUnicodeUseFallbacksMask,
text, kUnicodeUseFallbacksMask,
0, NULL, NULL, NULL,
1024, &iread, &olen, mactextbuf);
if (err != noErr && err != kTECUsedFallbacksStatus)
olen = 0;
} else if (s->font_charset != CS_NONE) {
/* XXX this is bogus if wchar_t and UniChar are different sizes. */
unitextptr = (wchar_t *)unitextbuf;
unitextptr = (wchar_t *)text;
olen = charset_from_unicode(&unitextptr, &len, mactextbuf, 1024,
s->font_charset, NULL, ".", 1);
} else

77
putty.h
View File

@ -40,35 +40,35 @@ typedef struct terminal_tag Terminal;
* ATTR_INVALID is an illegal colour combination.
*/
#define TATTR_ACTCURS 0x4UL /* active cursor (block) */
#define TATTR_PASCURS 0x2UL /* passive cursor (box) */
#define TATTR_RIGHTCURS 0x1UL /* cursor-on-RHS */
#define TATTR_ACTCURS 0x40000000UL /* active cursor (block) */
#define TATTR_PASCURS 0x20000000UL /* passive cursor (box) */
#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */
#define LATTR_NORM 0x00000000UL
#define LATTR_WIDE 0x01000000UL
#define LATTR_TOP 0x02000000UL
#define LATTR_BOT 0x03000000UL
#define LATTR_MODE 0x03000000UL
#define LATTR_WRAPPED 0x10000000UL
#define LATTR_WRAPPED2 0x20000000UL
#define LATTR_WIDE 0x00000001UL
#define LATTR_TOP 0x00000002UL
#define LATTR_BOT 0x00000003UL
#define LATTR_MODE 0x00000003UL
#define LATTR_WRAPPED 0x00000010UL
#define LATTR_WRAPPED2 0x00000020UL
#define ATTR_INVALID 0x03FF0000UL
#define ATTR_INVALID 0x03FFU
/* Like Linux use the F000 page for direct to font. */
#define ATTR_OEMCP 0x0000F000UL /* OEM Codepage DTF */
#define ATTR_ACP 0x0000F100UL /* Ansi Codepage DTF */
#define CSET_OEMCP 0x0000F000UL /* OEM Codepage DTF */
#define CSET_ACP 0x0000F100UL /* Ansi Codepage DTF */
/* These are internal use overlapping with the UTF-16 surrogates */
#define ATTR_ASCII 0x0000D800UL /* normal ASCII charset ESC ( B */
#define ATTR_LINEDRW 0x0000D900UL /* line drawing charset ESC ( 0 */
#define ATTR_SCOACS 0x0000DA00UL /* SCO Alternate charset */
#define ATTR_GBCHR 0x0000DB00UL /* UK variant charset ESC ( A */
#define CSET_MASK 0x0000FF00UL /* Character set mask; MUST be 0xFF00 */
#define CSET_ASCII 0x0000D800UL /* normal ASCII charset ESC ( B */
#define CSET_LINEDRW 0x0000D900UL /* line drawing charset ESC ( 0 */
#define CSET_SCOACS 0x0000DA00UL /* SCO Alternate charset */
#define CSET_GBCHR 0x0000DB00UL /* UK variant charset ESC ( A */
#define CSET_MASK 0xFFFFFF00UL /* Character set mask */
#define DIRECT_CHAR(c) ((c&0xFC00)==0xD800)
#define DIRECT_FONT(c) ((c&0xFE00)==0xF000)
#define DIRECT_CHAR(c) ((c&0xFFFFFC00)==0xD800)
#define DIRECT_FONT(c) ((c&0xFFFFFE00)==0xF000)
#define UCSERR (ATTR_LINEDRW|'a') /* UCS Format error character. */
#define UCSERR (CSET_LINEDRW|'a') /* UCS Format error character. */
/*
* UCSWIDE is a special value used in the terminal data to signify
* the character cell containing the right-hand half of a CJK wide
@ -79,27 +79,24 @@ typedef struct terminal_tag Terminal;
*/
#define UCSWIDE 0xDFFF
#define ATTR_NARROW 0x80000000UL
#define ATTR_WIDE 0x40000000UL
#define ATTR_BOLD 0x04000000UL
#define ATTR_UNDER 0x08000000UL
#define ATTR_REVERSE 0x10000000UL
#define ATTR_BLINK 0x20000000UL
#define ATTR_FGMASK 0x001F0000UL
#define ATTR_BGMASK 0x03E00000UL
#define ATTR_COLOURS 0x03FF0000UL
#define ATTR_FGSHIFT 16
#define ATTR_BGSHIFT 21
#define ATTR_NARROW 0x8000U
#define ATTR_WIDE 0x4000U
#define ATTR_BOLD 0x0400U
#define ATTR_UNDER 0x0800U
#define ATTR_REVERSE 0x1000U
#define ATTR_BLINK 0x2000U
#define ATTR_FGMASK 0x001FU
#define ATTR_BGMASK 0x03E0U
#define ATTR_COLOURS 0x03FFU
#define ATTR_FGSHIFT 0
#define ATTR_BGSHIFT 5
#define ATTR_DEFAULT 0x01280000UL /* bg 9, fg 8 */
#define ATTR_DEFFG 0x00080000UL
#define ATTR_DEFBG 0x01200000UL
#define ERASE_CHAR (ATTR_DEFAULT | ATTR_ASCII | ' ')
#define ATTR_MASK 0xFFFFFF00UL
#define CHAR_MASK 0x000000FFUL
#define ATTR_DEFAULT 0x0128U /* bg 9, fg 8 */
#define ATTR_DEFFG 0x0008U
#define ATTR_DEFBG 0x0120U
#define ATTR_CUR_AND (~(ATTR_BOLD|ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS))
#define ATTR_CUR_XOR 0x016A0000UL
#define ATTR_CUR_XOR 0x016AU
struct sesslist {
int nsessions;
@ -530,8 +527,8 @@ struct RSAKey; /* be a little careful of scope */
* Exports from window.c.
*/
void request_resize(void *frontend, int, int);
void do_text(Context, int, int, char *, int, unsigned long, int);
void do_cursor(Context, int, int, char *, int, unsigned long, int);
void do_text(Context, int, int, wchar_t *, int, unsigned long, int);
void do_cursor(Context, int, int, wchar_t *, int, unsigned long, int);
int char_width(Context ctx, int uc);
#ifdef OPTIMISE_SCROLL
void do_scroll(Context, int, int, int);

1221
terminal.c

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,21 @@ struct scrollregion {
};
#endif /* OPTIMISE_SCROLL */
typedef struct termchar termchar;
typedef struct termline termline;
struct termchar {
unsigned long chr;
unsigned long attr;
};
struct termline {
unsigned short lattr;
int cols;
int temporary; /* TRUE if decompressed from scrollback */
struct termchar *chars;
};
struct terminal_tag {
int compatibility_level;
@ -40,11 +55,11 @@ struct terminal_tag {
int tempsblines; /* number of lines in temporary
scrollback */
unsigned long *cpos; /* cursor position (convenience) */
termchar *cpos; /* cursor position (convenience) */
unsigned long *disptext; /* buffer of text on real screen */
unsigned long *dispcurs; /* location of cursor on real screen */
unsigned long curstype; /* type of cursor on real screen */
termline **disptext; /* buffer of text on real screen */
int dispcursx, dispcursy; /* location of cursor on real screen */
int curstype; /* type of cursor on real screen */
#define VBELL_TIMEOUT (TICKSPERSEC/10) /* visual bell lasts 1/10 sec */
@ -53,18 +68,18 @@ struct terminal_tag {
int beep_overloaded;
long lastbeep;
#define TTYPE unsigned long
#define TTYPE termchar
#define TSIZE (sizeof(TTYPE))
#define fix_cpos do { \
term->cpos = lineptr(term->curs.y) + term->curs.x; \
term->cpos = lineptr(term->curs.y)->chars + term->curs.x; \
} while(0)
#ifdef OPTIMISE_SCROLL
struct scrollregion *scrollhead, *scrolltail;
#endif /* OPTIMISE_SCROLL */
unsigned long default_attr, curr_attr, save_attr;
unsigned long erase_char;
int default_attr, curr_attr, save_attr;
termchar basic_erase_char, erase_char;
bufchain inbuf; /* terminal input buffer */
pos curs; /* cursor */
@ -112,7 +127,7 @@ struct terminal_tag {
int xterm_mouse; /* send mouse messages to app */
int mouse_is_down; /* used while tracking mouse buttons */
unsigned long cset_attr[2];
int cset_attr[2];
/*
* Saved settings on the alternate screen.
@ -173,7 +188,7 @@ struct terminal_tag {
short wordness[256];
/* Mask of attributes to pay attention to when painting. */
unsigned long attr_mask;
int attr_mask;
wchar_t *paste_buffer;
int paste_len, paste_pos, paste_hold;
@ -212,9 +227,9 @@ struct terminal_tag {
/*
* These are buffers used by the bidi and Arabic shaping code.
*/
unsigned long *ltemp;
termchar *ltemp;
bidi_char *wcFrom, *wcTo;
unsigned long **pre_bidi_cache, **post_bidi_cache;
termchar **pre_bidi_cache, **post_bidi_cache;
int bidi_cache_size;
};

View File

@ -465,7 +465,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
if (ucsdata->dbcs_screenfont || ucsdata->font_codepage == 0) {
get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 2);
for (i = 128; i < 256; i++)
ucsdata->unitab_font[i] = (WCHAR) (ATTR_ACP + i);
ucsdata->unitab_font[i] = (WCHAR) (CSET_ACP + i);
} else {
get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 1);
@ -497,7 +497,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
for (i = 0; i < 32; i++)
ucsdata->unitab_line[i] = (WCHAR) i;
for (i = 32; i < 256; i++)
ucsdata->unitab_line[i] = (WCHAR) (ATTR_ACP + i);
ucsdata->unitab_line[i] = (WCHAR) (CSET_ACP + i);
ucsdata->unitab_line[127] = (WCHAR) 127;
} else {
get_unitab(ucsdata->line_codepage, ucsdata->unitab_line, 0);
@ -561,15 +561,15 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
/* Generate line->screen direct conversion links. */
if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS)
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, ATTR_OEMCP);
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, CSET_OEMCP);
link_font(ucsdata->unitab_line, ucsdata->unitab_font, ATTR_ACP);
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, ATTR_ACP);
link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, ATTR_ACP);
link_font(ucsdata->unitab_line, ucsdata->unitab_font, CSET_ACP);
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, CSET_ACP);
link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, CSET_ACP);
if (cfg->vtmode == VT_OEMANSI || cfg->vtmode == VT_XWINDOWS) {
link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, ATTR_OEMCP);
link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, ATTR_OEMCP);
link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, CSET_OEMCP);
link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, CSET_OEMCP);
}
if (ucsdata->dbcs_screenfont &&
@ -577,7 +577,7 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
/* F***ing Microsoft fonts, Japanese and Korean codepage fonts
* have a currency symbol at 0x5C but their unicode value is
* still given as U+005C not the correct U+00A5. */
ucsdata->unitab_line['\\'] = ATTR_OEMCP + '\\';
ucsdata->unitab_line['\\'] = CSET_OEMCP + '\\';
}
/* Last chance, if !unicode then try poorman links. */
@ -593,17 +593,17 @@ void init_ucs(Config *cfg, struct unicode_data *ucsdata)
ucsdata->unitab_line[i] >= 160 &&
ucsdata->unitab_line[i] < 256) {
ucsdata->unitab_line[i] =
(WCHAR) (ATTR_ACP +
(WCHAR) (CSET_ACP +
poorman_latin1[ucsdata->unitab_line[i] - 160]);
}
for (i = 96; i < 127; i++)
if (!DIRECT_FONT(ucsdata->unitab_xterm[i]))
ucsdata->unitab_xterm[i] =
(WCHAR) (ATTR_ACP + poorman_vt100[i - 96]);
(WCHAR) (CSET_ACP + poorman_vt100[i - 96]);
for(i=128;i<256;i++)
if (!DIRECT_FONT(ucsdata->unitab_scoacs[i]))
ucsdata->unitab_scoacs[i] =
(WCHAR) (ATTR_ACP + poorman_scoacs[i - 128]);
(WCHAR) (CSET_ACP + poorman_scoacs[i - 128]);
}
}

View File

@ -1798,7 +1798,7 @@ void free_ctx(Context ctx)
*
* We are allowed to fiddle with the contents of `text'.
*/
void do_text_internal(Context ctx, int x, int y, char *text, int len,
void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
@ -1841,7 +1841,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
shadow = 1;
}
if (lattr != LATTR_NORM) {
if ((lattr & LATTR_MODE) != LATTR_NORM) {
x *= 2;
if (x >= inst->term->cols)
return;
@ -1876,7 +1876,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
wcs = snewn(len+1, wchar_t);
for (i = 0; i < len; i++) {
wcs[i] = (wchar_t) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
wcs[i] = text[i];
}
if (inst->fonts[fontid] == NULL) {
@ -1913,6 +1913,11 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
x*inst->font_width+inst->cfg.window_border,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gwcs, len*2);
if (shadow)
gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
x*inst->font_width+inst->cfg.window_border+inst->cfg.shadowboldoffset,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gwcs, len*2);
sfree(gwcs);
} else {
gcs = snewn(len+1, gchar);
@ -1922,18 +1927,16 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
x*inst->font_width+inst->cfg.window_border,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gcs, len);
if (shadow)
gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
x*inst->font_width+inst->cfg.window_border+inst->cfg.shadowboldoffset,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gcs, len);
sfree(gcs);
}
sfree(wcs);
}
if (shadow) {
gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
x*inst->font_width+inst->cfg.window_border + inst->cfg.shadowboldoffset,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
text, len);
}
if (attr & ATTR_UNDER) {
int uheight = inst->fonts[0]->ascent + 1;
if (uheight >= inst->font_height)
@ -1944,7 +1947,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
y*inst->font_height + uheight + inst->cfg.window_border);
}
if (lattr != LATTR_NORM) {
if ((lattr & LATTR_MODE) != LATTR_NORM) {
/*
* I can't find any plausible StretchBlt equivalent in the
* X server, so I'm going to do this the slow and painful
@ -1963,10 +1966,10 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
len * inst->font_width - i, inst->font_height);
}
len *= 2;
if (lattr != LATTR_WIDE) {
if ((lattr & LATTR_MODE) != LATTR_WIDE) {
int dt, db;
/* Now stretch vertically, in the same way. */
if (lattr == LATTR_BOT)
if ((lattr & LATTR_MODE) == LATTR_BOT)
dt = 0, db = 1;
else
dt = 1, db = 0;
@ -1982,7 +1985,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
}
}
void do_text(Context ctx, int x, int y, char *text, int len,
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
@ -1998,7 +2001,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
widefactor = 1;
}
if (lattr != LATTR_NORM) {
if ((lattr & LATTR_MODE) != LATTR_NORM) {
x *= 2;
if (x >= inst->term->cols)
return;
@ -2015,7 +2018,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
len*widefactor*inst->font_width, inst->font_height);
}
void do_cursor(Context ctx, int x, int y, char *text, int len,
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
@ -2042,7 +2045,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
widefactor = 1;
}
if (lattr != LATTR_NORM) {
if ((lattr & LATTR_MODE) != LATTR_NORM) {
x *= 2;
if (x >= inst->term->cols)
return;
@ -2070,7 +2073,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
int char_width;
if ((attr & ATTR_WIDE) || lattr != LATTR_NORM)
if ((attr & ATTR_WIDE) || (lattr & LATTR_MODE) != LATTR_NORM)
char_width = 2*inst->font_width;
else
char_width = inst->font_width;

115
window.c
View File

@ -2901,7 +2901,7 @@ static void sys_cursor_update(void)
*
* We are allowed to fiddle with the contents of `text'.
*/
void do_text(Context ctx, int x, int y, char *text, int len,
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
COLORREF fg, bg, t;
@ -2909,11 +2909,14 @@ void do_text(Context ctx, int x, int y, char *text, int len,
HDC hdc = ctx;
RECT line_box;
int force_manual_underline = 0;
int fnt_width = font_width * (1 + (lattr != LATTR_NORM));
int char_width = fnt_width;
int fnt_width, char_width;
int text_adjust = 0;
static int *IpDx = 0, IpDxLEN = 0;
lattr &= LATTR_MODE;
char_width = fnt_width = font_width * (1 + (lattr != LATTR_NORM));
if (attr & ATTR_WIDE)
char_width *= 2;
@ -2961,43 +2964,39 @@ void do_text(Context ctx, int x, int y, char *text, int len,
nfont |= FONT_NARROW;
/* Special hack for the VT100 linedraw glyphs. */
if ((attr & CSET_MASK) == 0x2300) {
if (text[0] >= (char) 0xBA && text[0] <= (char) 0xBD) {
switch ((unsigned char) (text[0])) {
case 0xBA:
text_adjust = -2 * font_height / 5;
break;
case 0xBB:
text_adjust = -1 * font_height / 5;
break;
case 0xBC:
text_adjust = font_height / 5;
break;
case 0xBD:
text_adjust = 2 * font_height / 5;
break;
}
if (lattr == LATTR_TOP || lattr == LATTR_BOT)
text_adjust *= 2;
attr &= ~CSET_MASK;
text[0] = (char) (ucsdata.unitab_xterm['q'] & CHAR_MASK);
attr |= (ucsdata.unitab_xterm['q'] & CSET_MASK);
if (attr & ATTR_UNDER) {
attr &= ~ATTR_UNDER;
force_manual_underline = 1;
}
if (text[0] >= 0x23BA && text[0] <= 0x23BD) {
switch ((unsigned char) (text[0])) {
case 0xBA:
text_adjust = -2 * font_height / 5;
break;
case 0xBB:
text_adjust = -1 * font_height / 5;
break;
case 0xBC:
text_adjust = font_height / 5;
break;
case 0xBD:
text_adjust = 2 * font_height / 5;
break;
}
if (lattr == LATTR_TOP || lattr == LATTR_BOT)
text_adjust *= 2;
text[0] = ucsdata.unitab_xterm['q'];
if (attr & ATTR_UNDER) {
attr &= ~ATTR_UNDER;
force_manual_underline = 1;
}
}
/* Anything left as an original character set is unprintable. */
if (DIRECT_CHAR(attr)) {
attr &= ~CSET_MASK;
attr |= 0xFF00;
memset(text, 0xFD, len);
if (DIRECT_CHAR(text[0])) {
int i;
for (i = 0; i < len; i++)
text[i] = 0xFFFD;
}
/* OEM CP */
if ((attr & CSET_MASK) == ATTR_OEMCP)
if ((text[0] & CSET_MASK) == CSET_OEMCP)
nfont |= FONT_OEM;
nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
@ -3044,7 +3043,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
line_box.right = font_width*term->cols+offset_width;
/* We're using a private area for direct to font. (512 chars.) */
if (ucsdata.dbcs_screenfont && (attr & CSET_MASK) == ATTR_ACP) {
if (ucsdata.dbcs_screenfont && (text[0] & CSET_MASK) == CSET_ACP) {
/* Ho Hum, dbcs fonts are a PITA! */
/* To display on W9x I have to convert to UCS */
static wchar_t *uni_buf = 0;
@ -3059,15 +3058,20 @@ void do_text(Context ctx, int x, int y, char *text, int len,
for(nlen = mptr = 0; mptr<len; mptr++) {
uni_buf[nlen] = 0xFFFD;
if (IsDBCSLeadByteEx(ucsdata.font_codepage, (BYTE) text[mptr])) {
char dbcstext[2];
dbcstext[0] = text[mptr] & 0xFF;
dbcstext[1] = text[mptr+1] & 0xFF;
IpDx[nlen] += char_width;
MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS,
text+mptr, 2, uni_buf+nlen, 1);
dbcstext, 2, uni_buf+nlen, 1);
mptr++;
}
else
{
char dbcstext[1];
dbcstext[0] = text[mptr] & 0xFF;
MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS,
text+mptr, 1, uni_buf+nlen, 1);
dbcstext, 1, uni_buf+nlen, 1);
}
nlen++;
}
@ -3086,10 +3090,21 @@ void do_text(Context ctx, int x, int y, char *text, int len,
}
IpDx[0] = -1;
} else if (DIRECT_FONT(attr)) {
} else if (DIRECT_FONT(text[0])) {
static char *directbuf = NULL;
static int directlen = 0;
int i;
if (len > directlen) {
directlen = len;
directbuf = sresize(directbuf, directlen, char);
}
for (i = 0; i < len; i++)
directbuf[i] = text[i] & 0xFF;
ExtTextOut(hdc, x,
y - font_height * (lattr == LATTR_BOT) + text_adjust,
ETO_CLIPPED | ETO_OPAQUE, &line_box, text, len, IpDx);
ETO_CLIPPED | ETO_OPAQUE, &line_box, directbuf, len, IpDx);
if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {
SetBkMode(hdc, TRANSPARENT);
@ -3103,7 +3118,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
ExtTextOut(hdc, x - 1,
y - font_height * (lattr ==
LATTR_BOT) + text_adjust,
ETO_CLIPPED, &line_box, text, len, IpDx);
ETO_CLIPPED, &line_box, directbuf, len, IpDx);
}
} else {
/* And 'normal' unicode characters */
@ -3116,7 +3131,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
wbuf = snewn(wlen, WCHAR);
}
for (i = 0; i < len; i++)
wbuf[i] = (WCHAR) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
wbuf[i] = text[i];
/* print Glyphs as they are, without Windows' Shaping*/
exact_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust,
@ -3151,7 +3166,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
}
}
void do_cursor(Context ctx, int x, int y, char *text, int len,
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr)
{
@ -3161,7 +3176,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
int ctype = cfg.cursor_type;
if ((attr & TATTR_ACTCURS) && (ctype == 0 || term->big_cursor)) {
if (((attr & CSET_MASK) | (unsigned char) *text) != UCSWIDE) {
if (*text != UCSWIDE) {
do_text(ctx, x, y, text, len, attr, lattr);
return;
}
@ -3238,13 +3253,13 @@ int char_width(Context ctx, int uc) {
if (!font_dualwidth) return 1;
switch (uc & CSET_MASK) {
case ATTR_ASCII:
case CSET_ASCII:
uc = ucsdata.unitab_line[uc & 0xFF];
break;
case ATTR_LINEDRW:
case CSET_LINEDRW:
uc = ucsdata.unitab_xterm[uc & 0xFF];
break;
case ATTR_SCOACS:
case CSET_SCOACS:
uc = ucsdata.unitab_scoacs[uc & 0xFF];
break;
}
@ -3252,12 +3267,12 @@ int char_width(Context ctx, int uc) {
if (ucsdata.dbcs_screenfont) return 1;
/* Speedup, I know of no font where ascii is the wrong width */
if ((uc&CHAR_MASK) >= ' ' && (uc&CHAR_MASK)<= '~')
if ((uc&~CSET_MASK) >= ' ' && (uc&~CSET_MASK)<= '~')
return 1;
if ( (uc & CSET_MASK) == ATTR_ACP ) {
if ( (uc & CSET_MASK) == CSET_ACP ) {
SelectObject(hdc, fonts[FONT_NORMAL]);
} else if ( (uc & CSET_MASK) == ATTR_OEMCP ) {
} else if ( (uc & CSET_MASK) == CSET_OEMCP ) {
another_font(FONT_OEM);
if (!fonts[FONT_OEM]) return 0;
@ -3265,8 +3280,8 @@ int char_width(Context ctx, int uc) {
} else
return 0;
if ( GetCharWidth32(hdc, uc&CHAR_MASK, uc&CHAR_MASK, &ibuf) != 1 &&
GetCharWidth(hdc, uc&CHAR_MASK, uc&CHAR_MASK, &ibuf) != 1)
if ( GetCharWidth32(hdc, uc&~CSET_MASK, uc&~CSET_MASK, &ibuf) != 1 &&
GetCharWidth(hdc, uc&~CSET_MASK, uc&~CSET_MASK, &ibuf) != 1)
return 0;
} else {
/* Speedup, I know of no font where ascii is the wrong width */