Index: src/faces.h =================================================================== RCS file: /var/cvsroot/xemacs/src/faces.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 faces.h --- src/faces.h 2000/01/12 07:54:47 1.1.1.1 +++ src/faces.h 2000/01/17 22:02:59 @@ -358,6 +358,8 @@ FACE_PROPERTY_INSTANCE (face, Qbackground_pixmap, domain, 0, Qzero) #define FACE_UNDERLINE_P(face, domain) \ (!NILP (FACE_PROPERTY_INSTANCE (face, Qunderline, domain, 0, Qzero))) +#define FACE_STRIKETHRU_P(face, domain) \ + (!NILP (FACE_PROPERTY_INSTANCE (face, Qstrikethru, domain, 0, Qzero))) #define FACE_HIGHLIGHT_P(face, domain) \ (!NILP (FACE_PROPERTY_INSTANCE (face, Qhighlight, domain, 0, Qzero))) #define FACE_DIM_P(face, domain) \ Index: src/glyphs-msw.c =================================================================== RCS file: /var/cvsroot/xemacs/src/glyphs-msw.c,v retrieving revision 1.2 diff -u -r1.2 glyphs-msw.c --- src/glyphs-msw.c 2000/01/17 04:43:52 1.2 +++ src/glyphs-msw.c 2000/01/17 22:05:19 @@ -2085,6 +2085,18 @@ /* subwindow and widget support */ /************************************************************************/ +static HFONT +mswindows_widget_hfont (struct Lisp_Image_Instance *p, + Lisp_Object domain) +{ + Lisp_Object face = IMAGE_INSTANCE_WIDGET_FACE (p); + int under = FACE_UNDERLINE_P (face, domain); + int strike = FACE_STRIKETHRU_P (face, domain); + Lisp_Object font = FACE_FONT (face, domain, Vcharset_ascii); + + return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike); +} + /* unmap the image if it is a widget. This is used by redisplay via redisplay_unmap_subwindows */ static void @@ -2160,12 +2172,8 @@ /* set the widget font from the widget face */ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), - WM_SETFONT, - (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT - (XFONT_INSTANCE (widget_face_font_info - (IMAGE_INSTANCE_SUBWINDOW_FRAME (p), - IMAGE_INSTANCE_WIDGET_FACE (p), - 0, 0))), + WM_SETFONT, (WPARAM) mswindows_widget_hfont + (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)), MAKELPARAM (TRUE, 0)); } } @@ -2396,11 +2404,7 @@ SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance)); /* set the widget font from the widget face */ SendMessage (wnd, WM_SETFONT, - (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT - (XFONT_INSTANCE (widget_face_font_info - (domain, - IMAGE_INSTANCE_WIDGET_FACE (ii), - 0, 0))), + (WPARAM) mswindows_widget_hfont (ii, domain), MAKELPARAM (TRUE, 0)); } Index: src/objects-msw.c =================================================================== RCS file: /var/cvsroot/xemacs/src/objects-msw.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 objects-msw.c --- src/objects-msw.c 2000/01/12 07:54:53 1.1.1.1 +++ src/objects-msw.c 2000/01/17 22:21:46 @@ -1041,6 +1041,58 @@ DeleteDC (hdc); } +static void +mswindows_create_font_variant (struct Lisp_Font_Instance* f, + int under, int strike) +{ + /* Cannot GC */ + + LOGFONT lf; + HFONT hfont; + + assert (FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, under, strike) == NULL); + + if (GetObject (FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, 0, 0), + sizeof (lf), (void*) &lf) == 0) + { + hfont = MSWINDOWS_BAD_HFONT; + } + else + { + lf.lfUnderline = under; + lf.lfStrikeOut = strike; + + hfont = CreateFontIndirect (&lf); + if (hfont == NULL) + hfont = MSWINDOWS_BAD_HFONT; + } + + FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, under, strike) = hfont; +} + +HFONT +mswindows_get_hfont (struct Lisp_Font_Instance* f, + int under, int strike) +{ + /* Cannot GC */ + HFONT hfont; + + if (FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, under, strike) == NULL) + mswindows_create_font_variant (f, under, strike); + + assert (FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, under, strike) != NULL); + + hfont = FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, under, strike); + + /* If strikeout/underline variant of the font could not be + created, then use the base version of the font */ + if (hfont == MSWINDOWS_BAD_HFONT) + hfont = FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f, 0, 0); + + assert (hfont != NULL && hfont != MSWINDOWS_BAD_HFONT); + + return hfont; +} /************************************************************************/ /* methods */ @@ -1129,15 +1181,7 @@ static void -mswindows_finalize_font_instance (struct Lisp_Font_Instance *f) -{ - if (f->data) - { - DeleteObject(f->data); - f->data=0; - } -} - +mswindows_finalize_font_instance (struct Lisp_Font_Instance *f); static int mswindows_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name, @@ -1151,7 +1195,7 @@ char effects[LF_FACESIZE], charset[LF_FACESIZE]; char *c; HDC hdc; - HFONT holdfont; + HFONT hfont, holdfont; TEXTMETRIC metrics; extname = XSTRING_DATA (name); @@ -1375,16 +1419,19 @@ } } - if ((f->data = CreateFontIndirect(&logfont)) == NULL) + if ((hfont = CreateFontIndirect(&logfont)) == NULL) { maybe_signal_simple_error ("Couldn't create font", name, Qfont, errb); return 0; } + f->data = xnew_and_zero (struct mswindows_font_instance_data); + FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f,0,0) = hfont; + hdc = CreateCompatibleDC (NULL); if (hdc) { - holdfont = SelectObject(hdc, f->data); + holdfont = SelectObject(hdc, hfont); if (holdfont) { GetTextMetrics (hdc, &metrics); @@ -1392,18 +1439,44 @@ DeleteDC (hdc); f->width = (unsigned short) metrics.tmAveCharWidth; f->height = (unsigned short) metrics.tmHeight; - f->ascent = (unsigned short) metrics.tmAscent; - f->descent = (unsigned short) metrics.tmDescent; + /* Font variant metrics hack. The problem is that in Windows + some underlined fonts have the descent of one pixel more + than their non-underlined counterparts. Font variants + though are assumed to have identical metrics. Lowering + the font's baseline one pixel down cures the problem, and + is visually undetectable. - kkm */ + f->ascent = (unsigned short) metrics.tmAscent - 1; + f->descent = (unsigned short) metrics.tmDescent + 1; f->proportional_p = (metrics.tmPitchAndFamily & TMPF_FIXED_PITCH); return 1; } DeleteDC (hdc); } + mswindows_finalize_font_instance (f); maybe_signal_simple_error ("Couldn't map font", name, Qfont, errb); return 0; } +static void +mswindows_finalize_font_instance (struct Lisp_Font_Instance *f) +{ + int i; + + if (f->data) + { + for (i = 0; i < MSWINDOWS_NUM_FONT_VARIANTS; i++) + { + if (FONT_INSTANCE_MSWINDOWS_HFONT_I (f, i) != NULL + && FONT_INSTANCE_MSWINDOWS_HFONT_I (f, i) != MSWINDOWS_BAD_HFONT) + DeleteObject (FONT_INSTANCE_MSWINDOWS_HFONT_I (f, i)); + } + + xfree (f->data); + f->data = 0; + } +} + #if 0 static void mswindows_mark_font_instance (struct Lisp_Font_Instance *f) @@ -1416,6 +1489,9 @@ Lisp_Object printcharfun, int escapeflag) { + char buf[10]; + sprintf (buf, " 0x%lx", FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f,0,0)); + write_c_string (buf, printcharfun); } static Lisp_Object Index: src/objects-msw.h =================================================================== RCS file: /var/cvsroot/xemacs/src/objects-msw.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 objects-msw.h --- src/objects-msw.h 2000/01/12 07:54:53 1.1.1.1 +++ src/objects-msw.h 2000/01/17 22:15:33 @@ -46,6 +46,32 @@ #define COLOR_INSTANCE_MSWINDOWS_COLOR(c) \ (MSWINDOWS_COLOR_INSTANCE_DATA (c)->color) -#define FONT_INSTANCE_MSWINDOWS_HFONT(c) ((HFONT) (c)->data) +/* The four HFONTS are for the 4 (underlined, strikethrough) + combinations. Only the one at index 0, neither underlined nor + struk through is created with the font instance. Other fonts are + created as necessary during redisplay, using the one at index 0 + as protptype */ +#define MSWINDOWS_NUM_FONT_VARIANTS 4 +struct mswindows_font_instance_data +{ + HFONT hfont [MSWINDOWS_NUM_FONT_VARIANTS]; +}; + +#define MSWINDOWS_FONT_INSTANCE_DATA(c) \ + ((struct mswindows_font_instance_data *) (c)->data) + +#define FONT_INSTANCE_MSWINDOWS_HFONT_I(c,i) \ + (MSWINDOWS_FONT_INSTANCE_DATA(c)->hfont[(i)]) + +#define FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT(c,under,strike) \ + FONT_INSTANCE_MSWINDOWS_HFONT_I (c, (!!(strike)<<1)|!!(under)) + +/* If font creation during redisplay fails, then the following + value is used to prevent future attempts to create this font. + Redisplay uses the "main" font when encounters this value */ +#define MSWINDOWS_BAD_HFONT INVALID_HANDLE_VALUE + +HFONT mswindows_get_hfont (struct Lisp_Font_Instance* f, + int under, int strike); #endif /* _XEMACS_OBJECTS_MSW_H_ */ Index: src/redisplay-msw.c =================================================================== RCS file: /var/cvsroot/xemacs/src/redisplay-msw.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 redisplay-msw.c --- src/redisplay-msw.c 2000/01/12 07:54:54 1.1.1.1 +++ src/redisplay-msw.c 2000/01/17 22:23:33 @@ -57,8 +57,10 @@ /* * Random forward declarations */ -static void mswindows_update_dc (HDC hdc, Lisp_Object font, Lisp_Object fg, - Lisp_Object bg, Lisp_Object bg_pmap); +static void mswindows_update_dc (HDC hdc, Lisp_Object fg, Lisp_Object bg, + Lisp_Object bg_pmap); +static void mswindows_set_dc_font (HDC hdc, Lisp_Object font, + int under, int strike); static void mswindows_output_vertical_divider (struct window *w, int clear); static void mswindows_redraw_exposed_windows (Lisp_Object window, int x, int y, int width, int height); @@ -191,31 +193,28 @@ else { assert(run->dimension == 1); /* #### FIXME! */ - mswindows_update_dc (hdc, font_inst, Qnil, Qnil, Qnil); + mswindows_set_dc_font (hdc, font_inst, + cachel->underline, cachel->strikethru); GetTextExtentPoint32 (hdc, run->ptr, run->len, &size); return(size.cx); } } - /***************************************************************************** mswindows_update_dc Given a number of parameters munge the DC so it has those properties. ****************************************************************************/ static void -mswindows_update_dc (HDC hdc, Lisp_Object font, Lisp_Object fg, - Lisp_Object bg, Lisp_Object bg_pmap) +mswindows_update_dc (HDC hdc, Lisp_Object fg, Lisp_Object bg, + Lisp_Object bg_pmap) { - if (!NILP (font)) - SelectObject(hdc, FONT_INSTANCE_MSWINDOWS_HFONT (XFONT_INSTANCE (font))); - - if (!NILP (fg)) { SetTextColor (hdc, COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (fg))); } + if (!NILP (bg)) { SetBkMode (hdc, OPAQUE); @@ -226,55 +225,14 @@ SetBkMode (hdc, TRANSPARENT); } } - - -/***************************************************************************** - mswindows_apply_face_effects - Draw underline and strikeout as if this was X. - #### On mswindows this really should be done as part of drawing the font. - The line width used is chosen arbitrarily from the font height. - ****************************************************************************/ -static void -mswindows_apply_face_effects (HDC hdc, struct display_line *dl, int xpos, - int width, struct Lisp_Font_Instance *fi, - struct face_cachel *cachel, - struct face_cachel *color_cachel) +static void mswindows_set_dc_font (HDC hdc, Lisp_Object font, + int under, int strike) { - int yclip; - HBRUSH brush, oldbrush; - RECT rect; - - brush = CreateSolidBrush (COLOR_INSTANCE_MSWINDOWS_COLOR ( - XCOLOR_INSTANCE (color_cachel->foreground))); - if (brush) - { - yclip = dl->ypos + dl->descent - dl->clip; - rect.left = xpos; - rect.right = xpos + width; - oldbrush = SelectObject (hdc, brush); - - if (cachel->underline) - { - rect.top = dl->ypos + dl->descent/2; - rect.bottom = rect.top + (fi->height >= 0x20 ? 2 : 1); - if (rect.bottom <= yclip) - FillRect (hdc, &rect, brush); - } - if (cachel->strikethru) - { - rect.top = dl->ypos + dl->descent - (dl->ascent + dl->descent)/2; - rect.bottom = rect.top + (fi->height >= 0x20 ? 2 : 1); - if (rect.bottom <= yclip) - FillRect (hdc, &rect, brush); - } - - SelectObject (hdc, oldbrush); - DeleteObject (brush); - } + SelectObject(hdc, mswindows_get_hfont (XFONT_INSTANCE (font), + under, strike)); } - /***************************************************************************** mswindows_output_hline @@ -321,15 +279,15 @@ start_pixpos, rb->width, &db, &dga); /* blank the background in the appropriate color */ - mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, cachel->foreground, - cachel->background, Qnil); + mswindows_update_dc (FRAME_MSWINDOWS_DC (f), + cachel->foreground, cachel->background, Qnil); redisplay_output_pixmap (w, bg_pmap, &db, &dga, rb->findex, 0, 0, 0, TRUE); } else { - mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, Qnil, - cachel->background, Qnil); + mswindows_update_dc (FRAME_MSWINDOWS_DC (f), + Qnil, cachel->background, Qnil); ExtTextOut (FRAME_MSWINDOWS_DC (f), 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); @@ -395,13 +353,13 @@ face_index = get_builtin_face_cache_index (w, Vtext_cursor_face); color_cachel = WINDOW_FACE_CACHEL (w, ((!cursor_p || bar_p) ? findex : face_index)); - mswindows_update_dc (hdc, font, color_cachel->foreground, + mswindows_update_dc (hdc, color_cachel->foreground, color_cachel->background, Qnil); + if (real_char_p) + mswindows_set_dc_font (hdc, font, + cachel->underline, cachel->strikethru); + ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE|ETO_CLIPPED, &rect, p_char, n_char, NULL); - if (real_char_p && (cachel->underline || cachel->strikethru)) - mswindows_apply_face_effects (hdc, dl, xpos, width, - XFONT_INSTANCE (font), - cachel, color_cachel); } if (!cursor_p) @@ -412,7 +370,7 @@ rect.right = rect.left + (EQ (bar, Qt) ? 1 : min (2, width)); face_index = get_builtin_face_cache_index (w, Vtext_cursor_face); cachel = WINDOW_FACE_CACHEL (w, face_index); - mswindows_update_dc (hdc, Qnil, Qnil, cachel->background, Qnil); + mswindows_update_dc (hdc, Qnil, cachel->background, Qnil); ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE, &rect, NULL, 0, NULL); } else if (!focus) @@ -430,14 +388,10 @@ face_index = get_builtin_face_cache_index (w, Vdefault_face); cachel = WINDOW_FACE_CACHEL (w, (real_char_p ? findex : face_index)); - mswindows_update_dc (hdc, Qnil, cachel->foreground, - cachel->background, Qnil); + mswindows_update_dc (hdc, + cachel->foreground, cachel->background, Qnil); ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE | ETO_CLIPPED, &rect, p_char, n_char, NULL); - if (cachel->underline || cachel->strikethru) - mswindows_apply_face_effects (hdc, dl, xpos+1, width-2, - XFONT_INSTANCE (font), - cachel, cachel); } } @@ -531,8 +485,8 @@ redisplay_calculate_display_boxes (dl, xpos + xoffset, 0, clip_start, width, &db, &dga); /* blank the background in the appropriate color */ - mswindows_update_dc (hdc, Qnil, cachel->foreground, - cachel->background, Qnil); + mswindows_update_dc (hdc, + cachel->foreground, cachel->background, Qnil); redisplay_output_pixmap (w, bg_pmap, &db, &dga, findex, 0, 0, 0, TRUE); /* output pixmap calls this so we have to recall to get correct @@ -552,8 +506,9 @@ if (EQ (font, Vthe_null_font_instance)) continue; - mswindows_update_dc (hdc, font, cachel->foreground, + mswindows_update_dc (hdc, cachel->foreground, NILP(bg_pmap) ? cachel->background : Qnil, Qnil); + mswindows_set_dc_font (hdc, font, cachel->underline, cachel->strikethru); this_width = mswindows_text_width_single_run (hdc, cachel, runs + i); @@ -579,11 +534,6 @@ NILP(bg_pmap) ? ETO_CLIPPED | ETO_OPAQUE : ETO_CLIPPED, &rect, (char *) runs[i].ptr, runs[i].len, NULL); - /* #### X does underline/strikethrough here so we do the same. - On mswindows, underline/strikethrough really belongs to the font */ - if (cachel->underline || cachel->strikethru) - mswindows_apply_face_effects (hdc, dl, xpos, this_width, fi, - cachel, cachel); xpos += this_width; } } @@ -711,7 +661,7 @@ /* Output the pixmap. Have to do this as many times as is required to fill the given area */ - mswindows_update_dc (hdc, Qnil, + mswindows_update_dc (hdc, WINDOW_FACE_CACHEL_FOREGROUND (w, findex), WINDOW_FACE_CACHEL_BACKGROUND (w, findex), Qnil); @@ -932,7 +882,7 @@ { RECT rect = { x, y, x + width, y + height }; Lisp_Object color = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); - mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, Qnil, color, Qnil); + mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, color, Qnil); DrawEdge (FRAME_MSWINDOWS_DC (f), &rect, edge, border); } @@ -1260,7 +1210,7 @@ { rect.top = y1; rect.bottom = y2; - mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, Qnil, + mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, DEFAULT_INDEX), Qnil); rect.right = WINDOW_RIGHT (w); rect.left = rect.right - spacing; @@ -1281,7 +1231,7 @@ { face_index div_face = get_builtin_face_cache_index (w, Vvertical_divider_face); - mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, Qnil, + mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, div_face), Qnil); ExtTextOut (FRAME_MSWINDOWS_DC (f), 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); @@ -1341,13 +1291,13 @@ { struct display_box db = { x, y, width, height }; mswindows_update_dc (FRAME_MSWINDOWS_DC (f), - Qnil, fcolor, bcolor, background_pixmap); + fcolor, bcolor, background_pixmap); mswindows_output_dibitmap_region ( f, XIMAGE_INSTANCE (background_pixmap), &db, 0); } else { - mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, Qnil, fcolor, Qnil); + mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, fcolor, Qnil); ExtTextOut (FRAME_MSWINDOWS_DC (f), 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); }