X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/5dd103a89c5b260320b322e17d125e1cf620c5bd..8df11cad382be13bc3250340039d2d07544b5995:/window.c diff --git a/window.c b/window.c index 39ac38dc..9f1dbe33 100644 --- a/window.c +++ b/window.c @@ -111,6 +111,7 @@ static struct unicode_data ucsdata; static int session_closed; static const struct telnet_special *specials; +static int n_specials; static struct { HMENU menu; @@ -686,8 +687,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) SetScrollInfo(hwnd, SB_VERT, &si, FALSE); } - start_backend(); - /* * Prepare the mouse handler. */ @@ -742,7 +741,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } } - update_specials_menu(NULL); + start_backend(); /* * Set up the initial input locale. @@ -917,20 +916,48 @@ void update_specials_menu(void *frontend) specials = NULL; if (specials) { - p = CreateMenu(); - for (i = 0; specials[i].name; i++) { + /* We can't use Windows to provide a stack for submenus, so + * here's a lame "stack" that will do for now. */ + HMENU saved_menu = NULL; + int nesting = 1; + p = CreatePopupMenu(); + for (i = 0; nesting > 0; i++) { assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX); - if (*specials[i].name) + switch (specials[i].code) { + case TS_SEP: + AppendMenu(p, MF_SEPARATOR, 0, 0); + break; + case TS_SUBMENU: + assert(nesting < 2); + nesting++; + saved_menu = p; /* XXX lame stacking */ + p = CreatePopupMenu(); + AppendMenu(saved_menu, MF_POPUP | MF_ENABLED, + (UINT) p, specials[i].name); + break; + case TS_EXITMENU: + nesting--; + if (nesting) { + p = saved_menu; /* XXX lame stacking */ + saved_menu = NULL; + } + break; + default: AppendMenu(p, MF_ENABLED, IDM_SPECIAL_MIN + 0x10 * i, specials[i].name); - else - AppendMenu(p, MF_SEPARATOR, 0, 0); + break; + } } - } else + /* Squirrel the highest special. */ + n_specials = i - 1; + } else { p = NULL; + n_specials = 0; + } for (j = 0; j < lenof(popup_menus); j++) { if (menu_already_exists) { + /* XXX does this free up all submenus? */ DeleteMenu(popup_menus[j].menu, popup_menus[j].specials_submenu_pos, MF_BYPOSITION); @@ -1136,7 +1163,7 @@ static void init_palette(void) */ static void exact_textout(HDC hdc, int x, int y, CONST RECT *lprc, unsigned short *lpString, UINT cbCount, - CONST INT *lpDx) + CONST INT *lpDx, int opaque) { GCP_RESULTSW gcpr; @@ -1152,10 +1179,11 @@ static void exact_textout(HDC hdc, int x, int y, CONST RECT *lprc, gcpr.nGlyphs = cbCount; GetCharacterPlacementW(hdc, lpString, cbCount, 0, &gcpr, - FLI_MASK | GCP_CLASSIN); + FLI_MASK | GCP_CLASSIN | GCP_DIACRITIC); - ExtTextOut(hdc, x, y, ETO_GLYPH_INDEX | ETO_CLIPPED | ETO_OPAQUE, lprc, - buffer, cbCount, lpDx); + ExtTextOut(hdc, x, y, + ETO_GLYPH_INDEX | ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0), + lprc, buffer, cbCount, lpDx); } /* @@ -2089,20 +2117,16 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } if (wParam >= IDM_SPECIAL_MIN && wParam <= IDM_SPECIAL_MAX) { int i = (wParam - IDM_SPECIAL_MIN) / 0x10; - int j; /* * Ensure we haven't been sent a bogus SYSCOMMAND * which would cause us to reference invalid memory * and crash. Perhaps I'm just too paranoid here. */ - for (j = 0; j < i; j++) - if (!specials || !specials[j].name) - break; - if (j == i) { - if (back) - back->special(backhandle, specials[i].code); - net_pending_errors(); - } + if (i >= n_specials) + break; + if (back) + back->special(backhandle, specials[i].code); + net_pending_errors(); } } break; @@ -2188,7 +2212,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, mi.rcMonitor.top == pt.y) { mouse_on_hotspot = 1; } - CloseHandle(mon); } } #else @@ -2901,19 +2924,22 @@ 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, - unsigned long attr, int lattr) +void do_text_internal(Context ctx, int x, int y, wchar_t *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 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 +2987,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); @@ -3033,7 +3055,10 @@ void do_text(Context ctx, int x, int y, char *text, int len, SelectObject(hdc, fonts[nfont]); SetTextColor(hdc, fg); SetBkColor(hdc, bg); - SetBkMode(hdc, OPAQUE); + if (attr & TATTR_COMBINING) + SetBkMode(hdc, TRANSPARENT); + else + SetBkMode(hdc, OPAQUE); line_box.left = x; line_box.top = y; line_box.right = x + char_width * len; @@ -3044,7 +3069,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 +3084,20 @@ void do_text(Context ctx, int x, int y, char *text, int len, for(nlen = mptr = 0; mptr 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,24 +3144,26 @@ 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 */ static WCHAR *wbuf = NULL; static int wlen = 0; int i; + if (wlen < len) { sfree(wbuf); wlen = 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, - &line_box, wbuf, len, IpDx); + &line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING)); /* ExtTextOutW(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx); @@ -3151,7 +3194,25 @@ 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, +/* + * Wrapper that handles combining characters. + */ +void do_text(Context ctx, int x, int y, wchar_t *text, int len, + unsigned long attr, int lattr) +{ + if (attr & TATTR_COMBINING) { + unsigned long a = 0; + attr &= ~TATTR_COMBINING; + while (len--) { + do_text_internal(ctx, x, y, text, 1, attr | a, lattr); + text++; + a = TATTR_COMBINING; + } + } else + do_text_internal(ctx, x, y, text, len, attr, lattr); +} + +void do_cursor(Context ctx, int x, int y, wchar_t *text, int len, unsigned long attr, int lattr) { @@ -3161,7 +3222,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 +3299,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 +3313,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 +3326,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 */