nlen = MultiByteToWideChar(font_codepage, MB_USEGLYPHCHARS, text, len, uni_buf, uni_len);
for(nlen = mptr = 0; mptr<len; mptr++) { uni_buf[nlen] = 0xFFFD; if (IsDBCSLeadByteEx(font_codepage, (BYTE) text[mptr])) { IpDx[nlen] += char_width; MultiByteToWideChar(font_codepage, MB_USEGLYPHCHARS, text+mptr, 2, uni_buf+nlen, 1); mptr++; } else { MultiByteToWideChar(font_codepage, MB_USEGLYPHCHARS, text+mptr, 1, uni_buf+nlen, 1); } nlen++; }
void do_text(Context ctx, int x, int y, char *text, int len,	     unsigned long attr, int lattr){    COLORREF fg, bg, t;    int nfg, nbg, nfont;    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 text_adjust = 0;    static int *IpDx = 0, IpDxLEN = 0;    if (attr & ATTR_WIDE)	char_width *= 2;    if (len > IpDxLEN || IpDx[0] != char_width) {	int i;	if (len > IpDxLEN) {	    sfree(IpDx);	    IpDx = smalloc((len + 16) * sizeof(int));	    IpDxLEN = (len + 16);	}	for (i = 0; i < IpDxLEN; i++)	    IpDx[i] = char_width;    }    x *= fnt_width;    y *= font_height;    if ((attr & TATTR_ACTCURS) && (cfg.cursor_type == 0 || big_cursor)) {	attr &= ATTR_CUR_AND | (bold_mode != BOLD_COLOURS ? ATTR_BOLD : 0);	attr ^= ATTR_CUR_XOR;    }    nfont = 0;    if (cfg.vtmode == VT_POORMAN && lattr != LATTR_NORM) {	/* Assume a poorman font is borken in other ways too. */	lattr = LATTR_WIDE;    } else	switch (lattr) {	  case LATTR_NORM:	    break;	  case LATTR_WIDE:	    nfont |= FONT_WIDE;	    break;	  default:	    nfont |= FONT_WIDE + FONT_HIGH;	    break;	}    /* Special hack for the VT100 linedraw glyphs. */    if ((attr & CSET_MASK) == 0x2300) {	if (!dbcs_screenfont &&	    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) (unitab_xterm['q'] & CHAR_MASK);	    attr |= (unitab_xterm['q'] & CSET_MASK);	    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, 0xFF, len);    }    /* OEM CP */    if ((attr & CSET_MASK) == ATTR_OEMCP)	nfont |= FONT_OEM;    nfg = 2 * ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);    nbg = 2 * ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);    if (bold_mode == BOLD_FONT && (attr & ATTR_BOLD))	nfont |= FONT_BOLD;    if (und_mode == UND_FONT && (attr & ATTR_UNDER))	nfont |= FONT_UNDERLINE;    another_font(nfont);    if (!fonts[nfont]) {	if (nfont & FONT_UNDERLINE)	    force_manual_underline = 1;	/* Don't do the same for manual bold, it could be bad news. */	nfont &= ~(FONT_BOLD | FONT_UNDERLINE);    }    another_font(nfont);    if (!fonts[nfont])	nfont = FONT_NORMAL;    if (attr & ATTR_REVERSE) {	t = nfg;	nfg = nbg;	nbg = t;    }    if (bold_mode == BOLD_COLOURS && (attr & ATTR_BOLD))	nfg++;    if (bold_mode == BOLD_COLOURS && (attr & ATTR_BLINK))	nbg++;    fg = colours[nfg];    bg = colours[nbg];    SelectObject(hdc, fonts[nfont]);    SetTextColor(hdc, fg);    SetBkColor(hdc, bg);    SetBkMode(hdc, OPAQUE);    line_box.left = x;    line_box.top = y;    line_box.right = x + char_width * len;    line_box.bottom = y + font_height;    /* We're using a private area for direct to font. (512 chars.) */    if (dbcs_screenfont && (attr & CSET_MASK) == ATTR_ACP) {	/* Ho Hum, dbcs fonts are a PITA! */	/* To display on W9x I have to convert to UCS */	static wchar_t *uni_buf = 0;	static int uni_len = 0;	int nlen;	if (len > uni_len) {	    sfree(uni_buf);	    uni_buf = smalloc((uni_len = len) * sizeof(wchar_t));	}	nlen = MultiByteToWideChar(font_codepage, MB_USEGLYPHCHARS,				   text, len, uni_buf, uni_len);	if (nlen <= 0)	    return;		       /* Eeek! */	ExtTextOutW(hdc, x,		    y - font_height * (lattr == LATTR_BOT) + text_adjust,		    ETO_CLIPPED | ETO_OPAQUE, &line_box, uni_buf, nlen, 0);	if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {	    SetBkMode(hdc, TRANSPARENT);	    ExtTextOutW(hdc, x - 1,			y - font_height * (lattr ==					   LATTR_BOT) + text_adjust,			ETO_CLIPPED, &line_box, uni_buf, nlen, 0);	}    } else if (DIRECT_FONT(attr)) {	ExtTextOut(hdc, x,		   y - font_height * (lattr == LATTR_BOT) + text_adjust,		   ETO_CLIPPED | ETO_OPAQUE, &line_box, text, len, IpDx);	if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {	    SetBkMode(hdc, TRANSPARENT);	    /* GRR: This draws the character outside it's box and can leave	     * 'droppings' even with the clip box! I suppose I could loop it	     * one character at a time ... yuk. 	     * 	     * Or ... I could do a test print with "W", and use +1 or -1 for this	     * shift depending on if the leftmost column is blank...	     */	    ExtTextOut(hdc, x - 1,		       y - font_height * (lattr ==					  LATTR_BOT) + text_adjust,		       ETO_CLIPPED, &line_box, text, len, IpDx);	}    } else {	/* And 'normal' unicode characters */	static WCHAR *wbuf = NULL;	static int wlen = 0;	int i;	if (wlen < len) {	    sfree(wbuf);	    wlen = len;	    wbuf = smalloc(wlen * sizeof(WCHAR));	}	for (i = 0; i < len; i++)	    wbuf[i] = (WCHAR) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));	ExtTextOutW(hdc, x,		    y - font_height * (lattr == LATTR_BOT) + text_adjust,		    ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx);	/* And the shadow bold hack. */	if (bold_mode == BOLD_SHADOW) {	    SetBkMode(hdc, TRANSPARENT);	    ExtTextOutW(hdc, x - 1,			y - font_height * (lattr ==					   LATTR_BOT) + text_adjust,			ETO_CLIPPED, &line_box, wbuf, len, IpDx);	}    }    if (lattr != LATTR_TOP && (force_manual_underline ||			       (und_mode == UND_LINE				&& (attr & ATTR_UNDER)))) {	HPEN oldpen;	int dec = descent;	if (lattr == LATTR_BOT)	    dec = dec * 2 - font_height;	oldpen = SelectObject(hdc, CreatePen(PS_SOLID, 0, fg));	MoveToEx(hdc, x, y + dec, NULL);	LineTo(hdc, x + len * char_width, y + dec);	oldpen = SelectObject(hdc, oldpen);	DeleteObject(oldpen);    }}