+ 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++;
+ }
+ 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, IpDx);
+ 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, IpDx);
+ }
+
+ IpDx[0] = -1;
+ } 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 && (attr & ATTR_BOLD)) {
+ 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);
+ }
+}
+
+void do_cursor(Context ctx, int x, int y, char *text, int len,
+ unsigned long attr, int lattr)
+{
+
+ int fnt_width;
+ int char_width;
+ HDC hdc = ctx;
+ int ctype = cfg.cursor_type;
+
+ if ((attr & TATTR_ACTCURS) && (ctype == 0 || big_cursor)) {
+ if (((attr & CSET_MASK) | (unsigned char) *text) != UCSWIDE) {
+ do_text(ctx, x, y, text, len, attr, lattr);
+ return;
+ }
+ ctype = 2;
+ attr |= TATTR_RIGHTCURS;
+ }
+
+ fnt_width = char_width = font_width * (1 + (lattr != LATTR_NORM));
+ if (attr & ATTR_WIDE)
+ char_width *= 2;
+ x *= fnt_width;
+ y *= font_height;
+ x += offset_width;
+ y += offset_height;
+
+ if ((attr & TATTR_PASCURS) && (ctype == 0 || big_cursor)) {
+ POINT pts[5];
+ HPEN oldpen;
+ pts[0].x = pts[1].x = pts[4].x = x;
+ pts[2].x = pts[3].x = x + char_width - 1;
+ pts[0].y = pts[3].y = pts[4].y = y;
+ pts[1].y = pts[2].y = y + font_height - 1;
+ oldpen = SelectObject(hdc, CreatePen(PS_SOLID, 0, colours[23]));
+ Polyline(hdc, pts, 5);
+ oldpen = SelectObject(hdc, oldpen);
+ DeleteObject(oldpen);
+ } else if ((attr & (TATTR_ACTCURS | TATTR_PASCURS)) && ctype != 0) {
+ int startx, starty, dx, dy, length, i;
+ if (ctype == 1) {
+ startx = x;
+ starty = y + descent;
+ dx = 1;
+ dy = 0;
+ length = char_width;
+ } else {
+ int xadjust = 0;
+ if (attr & TATTR_RIGHTCURS)
+ xadjust = char_width - 1;
+ startx = x + xadjust;
+ starty = y;
+ dx = 0;
+ dy = 1;
+ length = font_height;
+ }
+ if (attr & TATTR_ACTCURS) {
+ HPEN oldpen;
+ oldpen =
+ SelectObject(hdc, CreatePen(PS_SOLID, 0, colours[23]));
+ MoveToEx(hdc, startx, starty, NULL);
+ LineTo(hdc, startx + dx * length, starty + dy * length);
+ oldpen = SelectObject(hdc, oldpen);
+ DeleteObject(oldpen);
+ } else {
+ for (i = 0; i < length; i++) {
+ if (i % 2 == 0) {
+ SetPixel(hdc, startx, starty, colours[23]);
+ }
+ startx += dx;
+ starty += dy;
+ }
+ }
+ }
+}
+
+/* This function gets the actual width of a character in the normal font.
+ */
+int CharWidth(Context ctx, int uc) {
+ HDC hdc = ctx;
+ int ibuf = 0;
+
+ /* If the font max is the same as the font ave width then this
+ * function is a no-op.
+ */
+ if (!font_dualwidth) return 1;
+
+ switch (uc & CSET_MASK) {
+ case ATTR_ASCII:
+ uc = unitab_line[uc & 0xFF];
+ break;
+ case ATTR_LINEDRW:
+ uc = unitab_xterm[uc & 0xFF];
+ break;
+ case ATTR_SCOACS:
+ uc = unitab_scoacs[uc & 0xFF];
+ break;
+ }
+ if (DIRECT_FONT(uc)) {
+ if (dbcs_screenfont) return 1;
+
+ /* Speedup, I know of no font where ascii is the wrong width */
+ if ((uc&CHAR_MASK) >= ' ' && (uc&CHAR_MASK)<= '~')
+ return 1;
+
+ if ( (uc & CSET_MASK) == ATTR_ACP ) {
+ SelectObject(hdc, fonts[FONT_NORMAL]);
+ } else if ( (uc & CSET_MASK) == ATTR_OEMCP ) {
+ another_font(FONT_OEM);
+ if (!fonts[FONT_OEM]) return 0;
+
+ SelectObject(hdc, fonts[FONT_OEM]);
+ } else
+ return 0;
+
+ if ( GetCharWidth32(hdc, uc&CHAR_MASK, uc&CHAR_MASK, &ibuf) != 1 &&
+ GetCharWidth(hdc, uc&CHAR_MASK, uc&CHAR_MASK, &ibuf) != 1)
+ return 0;
+ } else {
+ /* Speedup, I know of no font where ascii is the wrong width */
+ if (uc >= ' ' && uc <= '~') return 1;
+
+ SelectObject(hdc, fonts[FONT_NORMAL]);
+ if ( GetCharWidth32W(hdc, uc, uc, &ibuf) == 1 )
+ /* Okay that one worked */ ;
+ else if ( GetCharWidthW(hdc, uc, uc, &ibuf) == 1 )
+ /* This should work on 9x too, but it's "less accurate" */ ;
+ else
+ return 0;
+ }
+
+ ibuf += font_width / 2 -1;
+ ibuf /= font_width;
+
+ return ibuf;
+}