X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/e9eee23e17d22e1def722b9c5f2779ac44db6ed9..6de0e1a2931f6b91a0fc8de1960e86dfb714def2:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index 7531dd0fd0..96d26344b5 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -1,6 +1,6 @@ /* Implementation of GUI terminal on the Microsoft W32 API. - Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001 - Free Software Foundation, Inc. + Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -16,8 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #include #include @@ -62,7 +62,8 @@ Boston, MA 02111-1307, USA. */ /* Fringe bitmaps. */ -static HBITMAP fringe_bmp[MAX_FRINGE_BITMAPS]; +static int max_fringe_bmp = 0; +static HBITMAP *fringe_bmp = 0; /* Non-nil means Emacs uses toolkit scroll bars. */ @@ -86,6 +87,10 @@ static int any_help_event_p; /* Last window where we saw the mouse. Used by mouse-autoselect-window. */ static Lisp_Object last_window; +/* Non-zero means make use of UNDERLINE_POSITION font properties. + (Not yet supported, see TODO in x_draw_glyph_string.) */ +int x_use_underline_position_properties; + extern unsigned int msh_mousewheel; extern void free_frame_menubar (); @@ -133,6 +138,9 @@ int w32_use_visible_system_caret; for Far East languages. */ int w32_enable_unicode_output; +/* Flag to enable Cleartype hack for font metrics. */ +static int cleartype_active; + DWORD dwWindowsThreadId = 0; HANDLE hWindowsThread = NULL; DWORD dwMainThreadId = 0; @@ -177,7 +185,7 @@ int last_scroll_bar_drag_pos; static RECT last_mouse_glyph; static Lisp_Object last_mouse_press_frame; -Lisp_Object Vw32_num_mouse_buttons; +int w32_num_mouse_buttons; Lisp_Object Vw32_swap_mouse_buttons; @@ -221,8 +229,6 @@ static int input_signal_count; extern Lisp_Object Vcommand_line_args, Vsystem_name; -extern Lisp_Object Qface, Qmouse_face; - #ifndef USE_CRT_DLL extern int errno; #endif @@ -256,12 +262,21 @@ static void frame_highlight P_ ((struct frame *)); static void frame_unhighlight P_ ((struct frame *)); static void x_new_focus_frame P_ ((struct w32_display_info *, struct frame *)); +static void x_focus_changed P_ ((int, int, struct w32_display_info *, + struct frame *, struct input_event *)); +static void w32_detect_focus_change P_ ((struct w32_display_info *, + W32Msg *, struct input_event *)); static void w32_frame_rehighlight P_ ((struct frame *)); static void x_frame_rehighlight P_ ((struct w32_display_info *)); static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int, enum text_cursor_kinds)); -static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, HDC)); +static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC)); +static BOOL my_show_window P_ ((struct frame *, HWND, int)); +static void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT)); +static void my_set_focus P_ ((struct frame *, HWND)); +static void my_set_foreground_window P_ ((HWND)); +static void my_destroy_window P_ ((struct frame *, HWND)); static Lisp_Object Qvendor_specific_keysyms; @@ -500,6 +515,7 @@ w32_draw_vertical_window_border (w, x, y0, y1) struct frame *f = XFRAME (WINDOW_FRAME (w)); RECT r; HDC hdc; + struct face *face; r.left = x; r.right = x + 1; @@ -507,7 +523,12 @@ w32_draw_vertical_window_border (w, x, y0, y1) r.bottom = y1; hdc = get_frame_dc (f); - w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r); + face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID); + if (face) + w32_fill_rect (f, hdc, face->foreground, &r); + else + w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r); + release_frame_dc (f, hdc); } @@ -541,7 +562,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) output_cursor.vpos, output_cursor.x, output_cursor.y); - x_draw_vertical_border (w); + if (draw_window_fringes (w, 1)) + x_draw_vertical_border (w); + UNBLOCK_INPUT; } @@ -626,11 +649,7 @@ x_after_update_window_line (desired_row) xassert (w); if (!desired_row->mode_line_p && !w->pseudo_window_p) - { - BLOCK_INPUT; - draw_row_fringe_bitmaps (w, desired_row); - UNBLOCK_INPUT; - } + desired_row->redraw_fringe_bitmaps_p = 1; /* When a window has disappeared, make sure that no rest of full-width rows stays visible in the internal border. Could @@ -680,34 +699,79 @@ w32_draw_fringe_bitmap (w, row, p) struct frame *f = XFRAME (WINDOW_FRAME (w)); HDC hdc; struct face *face = p->face; + int rowY; hdc = get_frame_dc (f); /* Must clip because of partially visible lines. */ - w32_clip_to_row (w, row, hdc); + rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + if (p->y < rowY) + { + /* Adjust position of "bottom aligned" bitmap on partially + visible last row. */ + int oldY = row->y; + int oldVH = row->visible_height; + row->visible_height = p->h; + row->y -= rowY - p->y; + w32_clip_to_row (w, row, -1, hdc); + row->y = oldY; + row->visible_height = oldVH; + } + else + w32_clip_to_row (w, row, -1, hdc); - if (p->bx >= 0) + if (p->bx >= 0 && !p->overlay_p) { w32_fill_area (f, hdc, face->background, p->bx, p->by, p->nx, p->ny); } - if (p->which != NO_FRINGE_BITMAP) + if (p->which && p->which < max_fringe_bmp) { HBITMAP pixmap = fringe_bmp[p->which]; HDC compat_hdc; HANDLE horig_obj; compat_hdc = CreateCompatibleDC (hdc); + SaveDC (hdc); horig_obj = SelectObject (compat_hdc, pixmap); - SetTextColor (hdc, face->background); - SetBkColor (hdc, face->foreground); - BitBlt (hdc, p->x, p->y, p->wd, p->h, - compat_hdc, 0, p->dh, - SRCCOPY); + /* Paint overlays transparently. */ + if (p->overlay_p) + { + HBRUSH h_brush, h_orig_brush; + + SetTextColor (hdc, BLACK_PIX_DEFAULT (f)); + SetBkColor (hdc, WHITE_PIX_DEFAULT (f)); + h_brush = CreateSolidBrush (face->foreground); + h_orig_brush = SelectObject (hdc, h_brush); + + BitBlt (hdc, p->x, p->y, p->wd, p->h, + compat_hdc, 0, p->dh, + DSTINVERT); + BitBlt (hdc, p->x, p->y, p->wd, p->h, + compat_hdc, 0, p->dh, + 0x2E064A); + BitBlt (hdc, p->x, p->y, p->wd, p->h, + compat_hdc, 0, p->dh, + DSTINVERT); + + SelectObject (hdc, h_orig_brush); + DeleteObject (h_brush); + } + else + { + SetTextColor (hdc, face->background); + SetBkColor (hdc, (p->cursor_p + ? f->output_data.w32->cursor_pixel + : face->foreground)); + + BitBlt (hdc, p->x, p->y, p->wd, p->h, + compat_hdc, 0, p->dh, + SRCCOPY); + } SelectObject (compat_hdc, horig_obj); DeleteDC (compat_hdc); @@ -719,6 +783,37 @@ w32_draw_fringe_bitmap (w, row, p) release_frame_dc (f, hdc); } +static void +w32_define_fringe_bitmap (which, bits, h, wd) + int which; + unsigned short *bits; + int h, wd; +{ + if (which >= max_fringe_bmp) + { + int i = max_fringe_bmp; + max_fringe_bmp = which + 20; + fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP)); + while (i < max_fringe_bmp) + fringe_bmp[i++] = 0; + } + + fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits); +} + +static void +w32_destroy_fringe_bitmap (which) + int which; +{ + if (which >= max_fringe_bmp) + return; + + if (fringe_bmp[which]) + DeleteObject (fringe_bmp[which]); + fringe_bmp[which] = 0; +} + + /* This is called when starting Emacs and when restarting after suspend. When starting Emacs, no window is mapped. And nothing @@ -746,8 +841,7 @@ w32_reset_terminal_modes (void) /* Function prototypes of this page. */ -static XCharStruct *w32_per_char_metric P_ ((XFontStruct *, - wchar_t *, int)); +XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int)); static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *)); @@ -827,6 +921,16 @@ w32_native_per_char_metric (font, char2b, font_type, pcm) int real_width; GetCharWidth (hdc, *char2b, *char2b, &real_width); #endif + if (cleartype_active) + { + /* Cleartype antialiasing causes characters to overhang + by a pixel on each side compared with what GetCharABCWidths + reports. */ + char_widths.abcA -= 1; + char_widths.abcC -= 1; + char_widths.abcB += 2; + } + pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC; #if 0 /* As far as I can tell, this is the best way to determine what @@ -884,7 +988,7 @@ w32_native_per_char_metric (font, char2b, font_type, pcm) } -static XCharStruct * +XCharStruct * w32_per_char_metric (font, char2b, font_type) XFontStruct *font; wchar_t *char2b; @@ -1123,9 +1227,9 @@ w32_text_out (s, x, y,chars,nchars) wchar_t * chars; int nchars; { - int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1; - if (s->gc->font->bdf) - w32_BDF_TextOut (s->gc->font->bdf, s->hdc, + int charset_dim = w32_font_is_double_byte (s->font) ? 2 : 1; + if (s->font->bdf) + w32_BDF_TextOut (s->font->bdf, s->hdc, x, y, (char *) chars, charset_dim, nchars * charset_dim, 0); else if (s->first_glyph->font_type == UNICODE_FONT) @@ -1136,7 +1240,6 @@ w32_text_out (s, x, y,chars,nchars) } - static void x_set_glyph_string_clipping P_ ((struct glyph_string *)); static void x_set_glyph_string_gc P_ ((struct glyph_string *)); static void x_draw_glyph_string_background P_ ((struct glyph_string *, @@ -1159,7 +1262,8 @@ static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP)); static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int, int, int, int)); static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int, - int, int, int, int, RECT *)); + int, int, int, int, int, int, + RECT *)); static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, int, int, int, RECT *)); @@ -1463,7 +1567,7 @@ x_draw_glyph_string_foreground (s) else x = s->x; - if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR)) + if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR)) SetBkMode (s->hdc, TRANSPARENT); else SetBkMode (s->hdc, OPAQUE); @@ -1740,9 +1844,10 @@ x_setup_relief_colors (s) static void w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, - raised_p, left_p, right_p, clip_rect) + raised_p, top_p, bot_p, left_p, right_p, clip_rect) struct frame *f; - int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p; + int left_x, top_y, right_x, bottom_y, width; + int top_p, bot_p, left_p, right_p, raised_p; RECT *clip_rect; { int i; @@ -1757,10 +1862,11 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, w32_set_clip_rectangle (hdc, clip_rect); /* Top. */ - for (i = 0; i < width; ++i) - w32_fill_area (f, hdc, gc.foreground, - left_x + i * left_p, top_y + i, - right_x - left_x - i * (left_p + right_p ) + 1, 1); + if (top_p) + for (i = 0; i < width; ++i) + w32_fill_area (f, hdc, gc.foreground, + left_x + i * left_p, top_y + i, + right_x - left_x - i * (left_p + right_p ) + 1, 1); /* Left. */ if (left_p) @@ -1775,10 +1881,11 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, gc.foreground = f->output_data.w32->white_relief.gc->foreground; /* Bottom. */ - for (i = 0; i < width; ++i) - w32_fill_area (f, hdc, gc.foreground, - left_x + i * left_p, bottom_y - i, - right_x - left_x - i * (left_p + right_p) + 1, 1); + if (bot_p) + for (i = 0; i < width; ++i) + w32_fill_area (f, hdc, gc.foreground, + left_x + i * left_p, bottom_y - i, + right_x - left_x - i * (left_p + right_p) + 1, 1); /* Right. */ if (right_p) @@ -1846,15 +1953,9 @@ x_draw_glyph_string_box (s) struct glyph *last_glyph; RECT clip_rect; - last_x = window_box_right (s->w, s->area); - if (s->row->full_width_p - && !s->w->pseudo_window_p) - { - last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w); - if (s->area != RIGHT_MARGIN_AREA - || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w)) - last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w); - } + last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) + ? WINDOW_RIGHT_EDGE_X (s->w) + : window_box_right (s->w, s->area)); /* The glyph that may have a right box line. */ last_glyph = (s->cmp || s->img @@ -1888,7 +1989,7 @@ x_draw_glyph_string_box (s) { x_setup_relief_colors (s); w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, - width, raised_p, left_p, right_p, &clip_rect); + width, raised_p, 1, 1, left_p, right_p, &clip_rect); } } @@ -1899,21 +2000,22 @@ static void x_draw_image_foreground (s) struct glyph_string *s; { - int x; - int y = s->ybase - image_ascent (s->img, s->face); + int x = s->x; + int y = s->ybase - image_ascent (s->img, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p) - x = s->x + abs (s->face->box_line_width); - else - x = s->x; + && s->first_glyph->left_box_line_p + && s->slice.x == 0) + x += abs (s->face->box_line_width); /* If there is a margin around the image, adjust x- and y-position by that margin. */ - x += s->img->hmargin; - y += s->img->vmargin; + if (s->slice.x == 0) + x += s->img->hmargin; + if (s->slice.y == 0) + y += s->img->vmargin; SaveDC (s->hdc); @@ -1935,12 +2037,12 @@ x_draw_image_foreground (s) SetTextColor (s->hdc, RGB (255, 255, 255)); SetBkColor (s->hdc, RGB (0, 0, 0)); - BitBlt (s->hdc, x, y, s->img->width, s->img->height, - compat_hdc, 0, 0, SRCINVERT); - BitBlt (s->hdc, x, y, s->img->width, s->img->height, - mask_dc, 0, 0, SRCAND); - BitBlt (s->hdc, x, y, s->img->width, s->img->height, - compat_hdc, 0, 0, SRCINVERT); + BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, + compat_hdc, s->slice.x, s->slice.y, SRCINVERT); + BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, + mask_dc, s->slice.x, s->slice.y, SRCAND); + BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, + compat_hdc, s->slice.x, s->slice.y, SRCINVERT); SelectObject (mask_dc, mask_orig_obj); DeleteDC (mask_dc); @@ -1950,8 +2052,8 @@ x_draw_image_foreground (s) SetTextColor (s->hdc, s->gc->foreground); SetBkColor (s->hdc, s->gc->background); - BitBlt (s->hdc, x, y, s->img->width, s->img->height, - compat_hdc, 0, 0, SRCCOPY); + BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, + compat_hdc, s->slice.x, s->slice.y, SRCCOPY); /* When the image has a mask, we can expect that at least part of a mouse highlight or a block cursor will @@ -1964,7 +2066,8 @@ x_draw_image_foreground (s) int r = s->img->relief; if (r < 0) r = -r; w32_draw_rectangle (s->hdc, s->gc, x - r, y - r , - s->img->width + r*2 - 1, s->img->height + r*2 - 1); + s->slice.width + r*2 - 1, + s->slice.height + r*2 - 1); } } @@ -1975,14 +2078,13 @@ x_draw_image_foreground (s) DeleteDC (compat_hdc); } else - w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1, - s->img->height - 1); + w32_draw_rectangle (s->hdc, s->gc, x, y, + s->slice.width - 1, s->slice.height - 1); RestoreDC (s->hdc ,-1); } - /* Draw a relief around the image glyph string S. */ static void @@ -1991,21 +2093,22 @@ x_draw_image_relief (s) { int x0, y0, x1, y1, thick, raised_p; RECT r; - int x; - int y = s->ybase - image_ascent (s->img, s->face); + int x = s->x; + int y = s->ybase - image_ascent (s->img, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p) - x = s->x + abs (s->face->box_line_width); - else - x = s->x; + && s->first_glyph->left_box_line_p + && s->slice.x == 0) + x += abs (s->face->box_line_width); /* If there is a margin around the image, adjust x- and y-position by that margin. */ - x += s->img->hmargin; - y += s->img->vmargin; + if (s->slice.x == 0) + x += s->img->hmargin; + if (s->slice.y == 0) + y += s->img->vmargin; if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) @@ -2021,12 +2124,17 @@ x_draw_image_relief (s) x0 = x - thick; y0 = y - thick; - x1 = x + s->img->width + thick - 1; - y1 = y + s->img->height + thick - 1; + x1 = x + s->slice.width + thick - 1; + y1 = y + s->slice.height + thick - 1; x_setup_relief_colors (s); get_glyph_string_clip_rect (s, &r); - w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r); + w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, + s->slice.y == 0, + s->slice.y + s->slice.height == s->img->height, + s->slice.x == 0, + s->slice.x + s->slice.width == s->img->width, + &r); } @@ -2039,21 +2147,22 @@ w32_draw_image_foreground_1 (s, pixmap) { HDC hdc = CreateCompatibleDC (s->hdc); HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap); - int x; - int y = s->ybase - s->y - image_ascent (s->img, s->face); + int x = 0; + int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p) - x = abs (s->face->box_line_width); - else - x = 0; + && s->first_glyph->left_box_line_p + && s->slice.x == 0) + x += abs (s->face->box_line_width); /* If there is a margin around the image, adjust x- and y-position by that margin. */ - x += s->img->hmargin; - y += s->img->vmargin; + if (s->slice.x == 0) + x += s->img->hmargin; + if (s->slice.y == 0) + y += s->img->vmargin; if (s->img->pixmap) { @@ -2069,12 +2178,12 @@ w32_draw_image_foreground_1 (s, pixmap) SetTextColor (hdc, RGB (0, 0, 0)); SetBkColor (hdc, RGB (255, 255, 255)); - BitBlt (hdc, x, y, s->img->width, s->img->height, - compat_hdc, 0, 0, SRCINVERT); - BitBlt (hdc, x, y, s->img->width, s->img->height, - mask_dc, 0, 0, SRCAND); - BitBlt (hdc, x, y, s->img->width, s->img->height, - compat_hdc, 0, 0, SRCINVERT); + BitBlt (hdc, x, y, s->slice.width, s->slice.height, + compat_hdc, s->slice.x, s->slice.y, SRCINVERT); + BitBlt (hdc, x, y, s->slice.width, s->slice.height, + mask_dc, s->slice.x, s->slice.y, SRCAND); + BitBlt (hdc, x, y, s->slice.width, s->slice.height, + compat_hdc, s->slice.x, s->slice.y, SRCINVERT); SelectObject (mask_dc, mask_orig_obj); DeleteDC (mask_dc); @@ -2084,8 +2193,8 @@ w32_draw_image_foreground_1 (s, pixmap) SetTextColor (hdc, s->gc->foreground); SetBkColor (hdc, s->gc->background); - BitBlt (hdc, x, y, s->img->width, s->img->height, - compat_hdc, 0, 0, SRCCOPY); + BitBlt (hdc, x, y, s->slice.width, s->slice.height, + compat_hdc, s->slice.x, s->slice.y, SRCCOPY); /* When the image has a mask, we can expect that at least part of a mouse highlight or a block cursor will @@ -2097,8 +2206,9 @@ w32_draw_image_foreground_1 (s, pixmap) { int r = s->img->relief; if (r < 0) r = -r; - w32_draw_rectangle (hdc, s->gc, x - r, y - r , - s->img->width + r*2 - 1, s->img->height + r*2 - 1); + w32_draw_rectangle (hdc, s->gc, x - r, y - r, + s->slice.width + r*2 - 1, + s->slice.height + r*2 - 1); } } @@ -2108,8 +2218,8 @@ w32_draw_image_foreground_1 (s, pixmap) DeleteDC (compat_hdc); } else - w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1, - s->img->height - 1); + w32_draw_rectangle (hdc, s->gc, x, y, + s->slice.width - 1, s->slice.height - 1); SelectObject (hdc, orig_hdc_obj); DeleteDC (hdc); @@ -2168,19 +2278,22 @@ x_draw_image_glyph_string (s) taller than image or if image has a clip mask to reduce flickering. */ s->stippled_p = s->face->stipple != 0; - if (height > s->img->height + if (height > s->slice.height || s->img->hmargin || s->img->vmargin || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width) { - if (box_line_hwidth && s->first_glyph->left_box_line_p) - x = s->x + box_line_hwidth; - else - x = s->x; + x = s->x; + if (s->first_glyph->left_box_line_p + && s->slice.x == 0) + x += box_line_hwidth; + + y = s->y; + if (s->slice.y == 0) + y += box_line_vwidth; - y = s->y + box_line_vwidth; #if 0 /* TODO: figure out if we need to do this on Windows. */ if (s->img->mask) { @@ -2335,7 +2448,7 @@ x_draw_glyph_string (s) /* If S draws into the background of its successor, draw the background of the successor first so that S can draw into it. This makes S->next use XDrawString instead of XDrawImageString. */ - if (s->next && s->right_overhang && !s->for_overlaps_p) + if (s->next && s->right_overhang && !s->for_overlaps) { xassert (s->next->img == NULL); x_set_glyph_string_gc (s->next); @@ -2348,7 +2461,7 @@ x_draw_glyph_string (s) /* Draw relief (if any) in advance for char/composition so that the glyph string can be drawn over it. */ - if (!s->for_overlaps_p + if (!s->for_overlaps && s->face->box != FACE_NO_BOX && (s->first_glyph->type == CHAR_GLYPH || s->first_glyph->type == COMPOSITE_GLYPH)) @@ -2374,7 +2487,7 @@ x_draw_glyph_string (s) break; case CHAR_GLYPH: - if (s->for_overlaps_p) + if (s->for_overlaps) s->background_filled_p = 1; else x_draw_glyph_string_background (s, 0); @@ -2382,7 +2495,7 @@ x_draw_glyph_string (s) break; case COMPOSITE_GLYPH: - if (s->for_overlaps_p || s->gidx > 0) + if (s->for_overlaps || s->gidx > 0) s->background_filled_p = 1; else x_draw_glyph_string_background (s, 1); @@ -2393,7 +2506,7 @@ x_draw_glyph_string (s) abort (); } - if (!s->for_overlaps_p) + if (!s->for_overlaps) { /* Draw underline. */ if (s->face->underline_p @@ -2403,7 +2516,9 @@ x_draw_glyph_string (s) unsigned long dy = s->height - h; /* TODO: Use font information for positioning and thickness - of underline. See OUTLINETEXTMETRIC, and xterm.c. */ + of underline. See OUTLINETEXTMETRIC, and xterm.c. + Note: If you make this work, don't forget to change the + doc string of x-use-underline-position-properties below. */ if (s->face->underline_defaulted_p) { w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, @@ -2428,7 +2543,7 @@ x_draw_glyph_string (s) } else { - w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x, + w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x, s->y + dy, s->width, h); } } @@ -2675,9 +2790,13 @@ x_scroll_run (w, run) /* If the dirty region is not what we expected, redraw the entire frame. */ if (!EqualRgn (combined, expect_dirty)) SET_FRAME_GARBAGED (f); + + DeleteObject (dirty); + DeleteObject (combined); } UNBLOCK_INPUT; + DeleteObject (expect_dirty); } @@ -2722,23 +2841,90 @@ x_new_focus_frame (dpyinfo, frame) if (old_focus && old_focus->auto_lower) x_lower_frame (old_focus); + if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise) + pending_autoraise_frame = dpyinfo->w32_focus_frame; + else + pending_autoraise_frame = 0; + } + x_frame_rehighlight (dpyinfo); +} +/* Handle FocusIn and FocusOut state changes for FRAME. + If FRAME has focus and there exists more than one frame, puts + a FOCUS_IN_EVENT into *BUFP. */ +static void +x_focus_changed (type, state, dpyinfo, frame, bufp) + int type; + int state; + struct w32_display_info *dpyinfo; + struct frame *frame; + struct input_event *bufp; +{ + if (type == WM_SETFOCUS) + { + if (dpyinfo->w32_focus_event_frame != frame) + { + x_new_focus_frame (dpyinfo, frame); + dpyinfo->w32_focus_event_frame = frame; + + /* Don't stop displaying the initial startup message + for a switch-frame event we don't need. */ + if (GC_NILP (Vterminal_frame) + && GC_CONSP (Vframe_list) + && !GC_NILP (XCDR (Vframe_list))) + { + bufp->kind = FOCUS_IN_EVENT; + XSETFRAME (bufp->frame_or_window, frame); + } + } + frame->output_data.x->focus_state |= state; + /* TODO: IME focus? */ + } + else if (type == WM_KILLFOCUS) + { + frame->output_data.x->focus_state &= ~state; + if (dpyinfo->w32_focus_event_frame == frame) + { + dpyinfo->w32_focus_event_frame = 0; + x_new_focus_frame (dpyinfo, 0); + } - if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise) - pending_autoraise_frame = dpyinfo->w32_focus_frame; - else - pending_autoraise_frame = 0; + /* TODO: IME focus? */ } +} - x_frame_rehighlight (dpyinfo); + +/* The focus may have changed. Figure out if it is a real focus change, + by checking both FocusIn/Out and Enter/LeaveNotify events. + + Returns FOCUS_IN_EVENT event in *BUFP. */ + +static void +w32_detect_focus_change (dpyinfo, event, bufp) + struct w32_display_info *dpyinfo; + W32Msg *event; + struct input_event *bufp; +{ + struct frame *frame; + + frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd); + if (! frame) + return; + + /* On w32, this is only called from focus events, so no switch needed. */ + x_focus_changed (event->msg.message, + (event->msg.message == WM_KILLFOCUS ? + FOCUS_IMPLICIT : FOCUS_EXPLICIT), + dpyinfo, frame, bufp); } + /* Handle an event saying the mouse has moved out of an Emacs frame. */ void @@ -3018,8 +3204,6 @@ construct_drag_n_drop (result, msg, f) static MSG last_mouse_motion_event; static Lisp_Object last_mouse_motion_frame; -static void remember_mouse_glyph P_ ((struct frame *, int, int)); - static void note_mouse_movement (frame, msg) FRAME_PTR frame; @@ -3041,9 +3225,9 @@ note_mouse_movement (frame, msg) /* Has the mouse moved off the glyph it was on at the last sighting? */ else if (mouse_x < last_mouse_glyph.left - || mouse_x > last_mouse_glyph.right + || mouse_x >= last_mouse_glyph.right || mouse_y < last_mouse_glyph.top - || mouse_y > last_mouse_glyph.bottom) + || mouse_y >= last_mouse_glyph.bottom) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; @@ -3052,7 +3236,7 @@ note_mouse_movement (frame, msg) gets called when mouse tracking is enabled but we also need to keep track of the mouse for help_echo and highlighting at other times. */ - remember_mouse_glyph (frame, mouse_x, mouse_y); + remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph); } } @@ -3064,9 +3248,6 @@ note_mouse_movement (frame, msg) static struct scroll_bar *x_window_to_scroll_bar (); static void x_scroll_bar_report_motion (); static void x_check_fullscreen P_ ((struct frame *)); -static void x_check_fullscreen_move P_ ((struct frame *)); -static int glyph_rect P_ ((struct frame *f, int, int, RECT *)); - static void redo_mouse_highlight () @@ -3085,108 +3266,6 @@ w32_define_cursor (window, cursor) { PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0); } - -/* Try to determine frame pixel position and size of the glyph under - frame pixel coordinates X/Y on frame F . Return the position and - size in *RECT. Value is non-zero if we could compute these - values. */ - -static int -glyph_rect (f, x, y, rect) - struct frame *f; - int x, y; - RECT *rect; -{ - Lisp_Object window; - - window = window_from_coordinates (f, x, y, 0, &x, &y, 0); - - if (!NILP (window)) - { - struct window *w = XWINDOW (window); - struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); - struct glyph_row *end = r + w->current_matrix->nrows - 1; - - for (; r < end && r->enabled_p; ++r) - if (r->y <= y && r->y + r->height > y) - { - /* Found the row at y. */ - struct glyph *g = r->glyphs[TEXT_AREA]; - struct glyph *end = g + r->used[TEXT_AREA]; - int gx; - - rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); - rect->bottom = rect->top + r->height; - - if (x < r->x) - { - /* x is to the left of the first glyph in the row. */ - /* Shouldn't this be a pixel value? - WINDOW_LEFT_EDGE_X (w) seems to be the right value. - ++KFS */ - rect->left = WINDOW_LEFT_EDGE_COL (w); - rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x); - return 1; - } - - for (gx = r->x; g < end; gx += g->pixel_width, ++g) - if (gx <= x && gx + g->pixel_width > x) - { - /* x is on a glyph. */ - rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx); - rect->right = rect->left + g->pixel_width; - return 1; - } - - /* x is to the right of the last glyph in the row. */ - rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx); - /* Shouldn't this be a pixel value? - WINDOW_RIGHT_EDGE_X (w) seems to be the right value. - ++KFS */ - rect->right = WINDOW_RIGHT_EDGE_COL (w); - return 1; - } - } - - /* The y is not on any row. */ - return 0; -} - -/* Record the position of the mouse in last_mouse_glyph. */ -static void -remember_mouse_glyph (f1, gx, gy) - struct frame * f1; - int gx, gy; -{ - if (!glyph_rect (f1, gx, gy, &last_mouse_glyph)) - { - int width = FRAME_SMALLEST_CHAR_WIDTH (f1); - int height = FRAME_SMALLEST_FONT_HEIGHT (f1); - - /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to - round down even for negative values. */ - if (gx < 0) - gx -= width - 1; - if (gy < 0) - gy -= height - 1; -#if 0 - /* This was the original code from XTmouse_position, but it seems - to give the position of the glyph diagonally next to the one - the mouse is over. */ - gx = (gx + width - 1) / width * width; - gy = (gy + height - 1) / height * height; -#else - gx = gx / width * width; - gy = gy / height * height; -#endif - - last_mouse_glyph.left = gx; - last_mouse_glyph.top = gy; - last_mouse_glyph.right = gx + width; - last_mouse_glyph.bottom = gy + height; - } -} - /* Return the current position of the mouse. *fp should be a frame which indicates which display to ask about. @@ -3289,7 +3368,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time) || insist); #else ScreenToClient (FRAME_W32_WINDOW (f1), &pt); - remember_mouse_glyph (f1, pt.x, pt.y); + remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph); #endif *bar_window = Qnil; @@ -3452,7 +3531,7 @@ my_create_scrollbar (f, bar) /*#define ATTACH_THREADS*/ -BOOL +static BOOL my_show_window (FRAME_PTR f, HWND hwnd, int how) { #ifndef ATTACH_THREADS @@ -3463,7 +3542,7 @@ my_show_window (FRAME_PTR f, HWND hwnd, int how) #endif } -void +static void my_set_window_pos (HWND hwnd, HWND hwndAfter, int x, int y, int cx, int cy, UINT flags) { @@ -3481,7 +3560,7 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter, #endif } -void +static void my_set_focus (f, hwnd) struct frame * f; HWND hwnd; @@ -3490,14 +3569,15 @@ my_set_focus (f, hwnd) (WPARAM) hwnd, 0); } -void +static void my_set_foreground_window (hwnd) HWND hwnd; { SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0); } -void + +static void my_destroy_window (f, hwnd) struct frame * f; HWND hwnd; @@ -4062,8 +4142,6 @@ static short temp_buffer[100]; This routine is called by the SIGIO handler. We return as soon as there are no more events to be read. - Events representing keys are stored in buffer BUFP, - which can hold up to NUMCHARS characters. We return the number of characters stored into the buffer, thus pretending to be `read'. @@ -4079,11 +4157,10 @@ static short temp_buffer[100]; */ int -w32_read_socket (sd, bufp, numchars, expected) +w32_read_socket (sd, expected, hold_quit) register int sd; - /* register */ struct input_event *bufp; - /* register */ int numchars; int expected; + struct input_event *hold_quit; { int count = 0; int check_visibility = 0; @@ -4103,13 +4180,16 @@ w32_read_socket (sd, bufp, numchars, expected) /* So people can tell when we have read the available input. */ input_signal_count++; - if (numchars <= 0) - abort (); /* Don't think this happens. */ - - /* TODO: tool-bars, ghostscript integration, mouse - cursors. */ + /* TODO: ghostscript integration. */ while (get_next_msg (&msg, FALSE)) { + struct input_event inev; + int do_help = 0; + + EVENT_INIT (inev); + inev.kind = NO_EVENT; + inev.arg = Qnil; + switch (msg.msg.message) { case WM_PAINT: @@ -4138,12 +4218,8 @@ w32_read_socket (sd, bufp, numchars, expected) visibility changes properly. */ if (f->iconified) { - bufp->kind = DEICONIFY_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.kind = DEICONIFY_EVENT; + XSETFRAME (inev.frame_or_window, f); } else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) @@ -4173,17 +4249,10 @@ w32_read_socket (sd, bufp, numchars, expected) if (f) { - if (numchars == 0) - abort (); - - bufp->kind = LANGUAGE_CHANGE_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->code = msg.msg.wParam; - bufp->modifiers = msg.msg.lParam & 0xffff; - bufp++; - count++; - numchars--; + inev.kind = LANGUAGE_CHANGE_EVENT; + XSETFRAME (inev.frame_or_window, f); + inev.code = msg.msg.wParam; + inev.modifiers = msg.msg.lParam & 0xffff; } break; @@ -4195,22 +4264,18 @@ w32_read_socket (sd, bufp, numchars, expected) { if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) { - dpyinfo->mouse_face_hidden = 1; clear_mouse_face (dpyinfo); + dpyinfo->mouse_face_hidden = 1; } if (temp_index == sizeof temp_buffer / sizeof (short)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; - bufp->kind = NON_ASCII_KEYSTROKE_EVENT; - bufp->code = msg.msg.wParam; - bufp->modifiers = msg.dwModifiers; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->timestamp = msg.msg.time; - bufp++; - numchars--; - count++; + inev.kind = NON_ASCII_KEYSTROKE_EVENT; + inev.code = msg.msg.wParam; + inev.modifiers = msg.dwModifiers; + XSETFRAME (inev.frame_or_window, f); + inev.timestamp = msg.msg.time; } break; @@ -4222,22 +4287,18 @@ w32_read_socket (sd, bufp, numchars, expected) { if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) { - dpyinfo->mouse_face_hidden = 1; clear_mouse_face (dpyinfo); + dpyinfo->mouse_face_hidden = 1; } if (temp_index == sizeof temp_buffer / sizeof (short)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; - bufp->kind = ASCII_KEYSTROKE_EVENT; - bufp->code = msg.msg.wParam; - bufp->modifiers = msg.dwModifiers; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp->timestamp = msg.msg.time; - bufp++; - numchars--; - count++; + inev.kind = ASCII_KEYSTROKE_EVENT; + inev.code = msg.msg.wParam; + inev.modifiers = msg.dwModifiers; + XSETFRAME (inev.frame_or_window, f); + inev.timestamp = msg.msg.time; } break; @@ -4283,13 +4344,10 @@ w32_read_socket (sd, bufp, numchars, expected) iff it is active. */ if (WINDOWP(window) && !EQ (window, last_window) - && !EQ (window, selected_window) - && numchars > 0) + && !EQ (window, selected_window)) { - bufp->kind = SELECT_WINDOW_EVENT; - bufp->frame_or_window = window; - bufp->arg = Qnil; - ++bufp, ++count, --numchars; + inev.kind = SELECT_WINDOW_EVENT; + inev.frame_or_window = window; } last_window=window; @@ -4305,29 +4363,16 @@ w32_read_socket (sd, bufp, numchars, expected) /* If the contents of the global variable help_echo_string has changed, generate a HELP_EVENT. */ +#if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE. + But it was originally changed to this to fix a bug, so I have + not removed it completely in case the bug is still there. */ if (help_echo_string != previous_help_echo_string || (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved)) - { - Lisp_Object frame; - int n; - - if (help_echo_string == Qnil) - { - help_echo_object = help_echo_window = Qnil; - help_echo_pos = -1; - } - - if (f) - XSETFRAME (frame, f); - else - frame = Qnil; - - any_help_event_p = 1; - n = gen_help_event (bufp, numchars, help_echo_string, frame, - help_echo_window, help_echo_object, - help_echo_pos); - bufp += n, count += n, numchars -= n; - } +#else /* This is what xterm.c does. */ + if (!NILP (help_echo_string) + || !NILP (previous_help_echo_string)) + do_help = 1; +#endif break; case WM_LBUTTONDOWN: @@ -4341,13 +4386,10 @@ w32_read_socket (sd, bufp, numchars, expected) { /* If we decide we want to generate an event to be seen by the rest of Emacs, we put it here. */ - struct input_event emacs_event; int tool_bar_p = 0; int button; int up; - emacs_event.kind = NO_EVENT; - if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) f = last_mouse_frame; @@ -4356,35 +4398,29 @@ w32_read_socket (sd, bufp, numchars, expected) if (f) { - construct_mouse_click (&emacs_event, &msg, f); + construct_mouse_click (&inev, &msg, f); /* Is this in the tool-bar? */ if (WINDOWP (f->tool_bar_window) && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window))) { Lisp_Object window; - int x = XFASTINT (emacs_event.x); - int y = XFASTINT (emacs_event.y); + int x = XFASTINT (inev.x); + int y = XFASTINT (inev.y); window = window_from_coordinates (f, x, y, 0, 0, 0, 1); if (EQ (window, f->tool_bar_window)) { - w32_handle_tool_bar_click (f, &emacs_event); + w32_handle_tool_bar_click (f, &inev); tool_bar_p = 1; } } - if (!tool_bar_p) - if (!dpyinfo->w32_focus_frame - || f == dpyinfo->w32_focus_frame - && (numchars >= 1)) - { - construct_mouse_click (bufp, &msg, f); - bufp++; - count++; - numchars--; - } + if (tool_bar_p + || (dpyinfo->w32_focus_frame + && f != dpyinfo->w32_focus_frame)) + inev.kind = NO_EVENT; } parse_button (msg.msg.message, HIWORD (msg.msg.wParam), @@ -4422,15 +4458,11 @@ w32_read_socket (sd, bufp, numchars, expected) if (f) { - if ((!dpyinfo->w32_focus_frame - || f == dpyinfo->w32_focus_frame) - && (numchars >= 1)) + if (!dpyinfo->w32_focus_frame + || f == dpyinfo->w32_focus_frame) { /* Emit an Emacs wheel-up/down event. */ - construct_mouse_wheel (bufp, &msg, f); - bufp++; - count++; - numchars--; + construct_mouse_wheel (&inev, &msg, f); } /* Ignore any mouse motion that happened before this event; any subsequent mouse-movement Emacs events @@ -4447,12 +4479,7 @@ w32_read_socket (sd, bufp, numchars, expected) f = x_window_to_frame (dpyinfo, msg.msg.hwnd); if (f) - { - construct_drag_n_drop (bufp, &msg, f); - bufp++; - count++; - numchars--; - } + construct_drag_n_drop (&inev, &msg, f); break; case WM_VSCROLL: @@ -4460,15 +4487,8 @@ w32_read_socket (sd, bufp, numchars, expected) struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam); - if (bar && numchars >= 1) - { - if (w32_scroll_bar_handle_click (bar, &msg, bufp)) - { - bufp++; - count++; - numchars--; - } - } + if (bar) + w32_scroll_bar_handle_click (bar, &msg, &inev); break; } @@ -4476,7 +4496,6 @@ w32_read_socket (sd, bufp, numchars, expected) f = x_window_to_frame (dpyinfo, msg.msg.hwnd); if (f) { - x_check_fullscreen_move(f); if (f->want_fullscreen & FULLSCREEN_WAIT) f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH); } @@ -4545,12 +4564,8 @@ w32_read_socket (sd, bufp, numchars, expected) f->async_visible = 0; f->async_iconified = 1; - bufp->kind = ICONIFY_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.kind = ICONIFY_EVENT; + XSETFRAME (inev.frame_or_window, f); break; case SIZE_MAXIMIZED: @@ -4558,7 +4573,7 @@ w32_read_socket (sd, bufp, numchars, expected) f->async_visible = 1; f->async_iconified = 0; - /* wait_reading_process_input will notice this and update + /* wait_reading_process_output will notice this and update the frame's display structures. */ SET_FRAME_GARBAGED (f); @@ -4575,12 +4590,8 @@ w32_read_socket (sd, bufp, numchars, expected) f->left_pos = x; f->top_pos = y; - bufp->kind = DEICONIFY_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.kind = DEICONIFY_EVENT; + XSETFRAME (inev.frame_or_window, f); } else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) @@ -4648,42 +4659,18 @@ w32_read_socket (sd, bufp, numchars, expected) Otherwise, the startup message is cleared when the mouse leaves the frame. */ if (any_help_event_p) - { - Lisp_Object frame; - int n; - - XSETFRAME (frame, f); - help_echo_string = Qnil; - n = gen_help_event (bufp, numchars, - Qnil, frame, Qnil, Qnil, 0); - bufp += n, count += n, numchars -= n; - } + do_help = -1; } break; case WM_SETFOCUS: - /* TODO: Port this change: - 2002-06-28 Jan D. - * xterm.h (struct x_output): Add focus_state. - * xterm.c (x_focus_changed): New function. - (x_detect_focus_change): New function. - (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut - EnterNotify and LeaveNotify to track X focus changes. - */ - f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd); - - dpyinfo->w32_focus_event_frame = f; - - if (f) - x_new_focus_frame (dpyinfo, f); - + w32_detect_focus_change (dpyinfo, &msg, &inev); dpyinfo->grabbed = 0; check_visibility = 1; break; case WM_KILLFOCUS: - /* TODO: some of this belongs in MOUSE_LEAVE */ f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd); if (f) @@ -4707,16 +4694,7 @@ w32_read_socket (sd, bufp, numchars, expected) Otherwise, the startup message is cleared when the mouse leaves the frame. */ if (any_help_event_p) - { - Lisp_Object frame; - int n; - - XSETFRAME (frame, f); - help_echo_string = Qnil; - n = gen_help_event (bufp, numchars, - Qnil, frame, Qnil, Qnil, 0); - bufp += n, count += n, numchars -=n; - } + do_help = -1; } dpyinfo->grabbed = 0; @@ -4728,15 +4706,8 @@ w32_read_socket (sd, bufp, numchars, expected) if (f) { - if (numchars == 0) - abort (); - - bufp->kind = DELETE_WINDOW_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.kind = DELETE_WINDOW_EVENT; + XSETFRAME (inev.frame_or_window, f); } break; @@ -4745,15 +4716,8 @@ w32_read_socket (sd, bufp, numchars, expected) if (f) { - if (numchars == 0) - abort (); - - bufp->kind = MENU_BAR_ACTIVATE_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + inev.kind = MENU_BAR_ACTIVATE_EVENT; + XSETFRAME (inev.frame_or_window, f); } break; @@ -4795,6 +4759,42 @@ w32_read_socket (sd, bufp, numchars, expected) } break; } + + if (inev.kind != NO_EVENT) + { + kbd_buffer_store_event_hold (&inev, hold_quit); + count++; + } + + if (do_help + && !(hold_quit && hold_quit->kind != NO_EVENT)) + { + Lisp_Object frame; + + if (f) + XSETFRAME (frame, f); + else + frame = Qnil; + + if (do_help > 0) + { + if (NILP (help_echo_string)) + { + help_echo_object = help_echo_window = Qnil; + help_echo_pos = -1; + } + + any_help_event_p = 1; + gen_help_event (help_echo_string, frame, help_echo_window, + help_echo_object, help_echo_pos); + } + else + { + help_echo_string = Qnil; + gen_help_event (Qnil, frame, Qnil, Qnil, 0); + } + count++; + } } /* If the focus was just given to an autoraising frame, @@ -4882,7 +4882,6 @@ w32_read_socket (sd, bufp, numchars, expected) } - /*********************************************************************** Text Cursor @@ -4896,18 +4895,19 @@ w32_read_socket (sd, bufp, numchars, expected) mode lines must be clipped to the whole window. */ static void -w32_clip_to_row (w, row, hdc) +w32_clip_to_row (w, row, area, hdc) struct window *w; struct glyph_row *row; + int area; HDC hdc; { struct frame *f = XFRAME (WINDOW_FRAME (w)); RECT clip_rect; - int window_y, window_width; + int window_x, window_y, window_width; - window_box (w, -1, 0, &window_y, &window_width, 0); + window_box (w, area, &window_x, &window_y, &window_width, 0); - clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0); + clip_rect.left = window_x; clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); clip_rect.top = max (clip_rect.top, window_y); clip_rect.right = clip_rect.left + window_width; @@ -4927,37 +4927,25 @@ x_draw_hollow_cursor (w, row) struct frame *f = XFRAME (WINDOW_FRAME (w)); HDC hdc; RECT rect; - int wd; + int h; struct glyph *cursor_glyph; HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel); - /* Compute frame-relative coordinates from window-relative - coordinates. */ - rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y) - + row->ascent - w->phys_cursor_ascent); - rect.bottom = rect.top + row->height; - /* Get the glyph the cursor is on. If we can't tell because the current matrix is invalid or such, give up. */ cursor_glyph = get_phys_cursor_glyph (w); if (cursor_glyph == NULL) return; - /* Compute the width of the rectangle to draw. If on a stretch - glyph, and `x-stretch-block-cursor' is nil, don't draw a - rectangle as wide as the glyph, but use a canonical character - width instead. */ - wd = cursor_glyph->pixel_width; - if (cursor_glyph->type == STRETCH_GLYPH - && !x_stretch_cursor_p) - wd = min (FRAME_COLUMN_WIDTH (f), wd); - w->phys_cursor_width = wd; + /* Compute frame-relative coordinates for phys cursor. */ + rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h); + rect.bottom = rect.top + h; + rect.right = rect.left + w->phys_cursor_width; - rect.right = rect.left + wd; hdc = get_frame_dc (f); /* Set clipping, draw the rectangle, and reset clipping again. */ - w32_clip_to_row (w, row, hdc); + w32_clip_to_row (w, row, TEXT_AREA, hdc); FrameRect (hdc, &rect, hb); DeleteObject (hb); w32_set_clip_rectangle (hdc, NULL); @@ -5023,7 +5011,7 @@ x_draw_bar_cursor (w, row, width, kind) hdc = get_frame_dc (f); - w32_clip_to_row (w, row, hdc); + w32_clip_to_row (w, row, TEXT_AREA, hdc); if (kind == BAR_CURSOR) { @@ -5086,6 +5074,9 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act cursor remains invisible. */ if (w32_use_visible_system_caret) { + /* Call to erase_phys_cursor here seems to use the + wrong values of w->phys_cursor, as they have been + overwritten before this function was called. */ if (w->phys_cursor_type != NO_CURSOR) erase_phys_cursor (w); @@ -5125,6 +5116,14 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0); } + if (glyph_row->exact_window_width_line_p + && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) + { + glyph_row->cursor_in_fringe_p = 1; + draw_fringe_bitmap (w, glyph_row, 0); + return; + } + switch (cursor_type) { case HOLLOW_BOX_CURSOR: @@ -5162,16 +5161,25 @@ x_bitmap_icon (f, icon) struct frame *f; Lisp_Object icon; { - HANDLE hicon; + HANDLE main_icon; + HANDLE small_icon = NULL; if (FRAME_W32_WINDOW (f) == 0) return 1; if (NILP (icon)) - hicon = LoadIcon (hinst, EMACS_CLASS); + main_icon = LoadIcon (hinst, EMACS_CLASS); else if (STRINGP (icon)) - hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0, - LR_DEFAULTSIZE | LR_LOADFROMFILE); + { + /* Load the main icon from the named file. */ + main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0, + LR_DEFAULTSIZE | LR_LOADFROMFILE); + /* Try to load a small icon to go with it. */ + small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON, + GetSystemMetrics (SM_CXSMICON), + GetSystemMetrics (SM_CYSMICON), + LR_LOADFROMFILE); + } else if (SYMBOLP (icon)) { LPCTSTR name; @@ -5191,16 +5199,21 @@ x_bitmap_icon (f, icon) else return 1; - hicon = LoadIcon (NULL, name); + main_icon = LoadIcon (NULL, name); } else return 1; - if (hicon == NULL) + if (main_icon == NULL) return 1; PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG, - (LPARAM) hicon); + (LPARAM) main_icon); + + /* If there is a small icon that goes with it, set that too. */ + if (small_icon) + PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL, + (LPARAM) small_icon); return 0; } @@ -5252,7 +5265,8 @@ x_new_font (f, fontname) FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset; FRAME_FONTSET (f) = -1; - FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f)); + FRAME_COLUMN_WIDTH (f) = fontp->average_width; + FRAME_SPACE_WIDTH (f) = fontp->space_width; FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f)); compute_fringe_widths (f, 1); @@ -5336,47 +5350,17 @@ void x_calc_absolute_position (f) struct frame *f; { - POINT pt; int flags = f->size_hint_flags; - pt.x = pt.y = 0; - - /* Find the position of the outside upper-left corner of - the inner window, with respect to the outer window. - But do this only if we will need the results. */ - if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window) - { - BLOCK_INPUT; - MapWindowPoints (FRAME_W32_WINDOW (f), - f->output_data.w32->parent_desc, - &pt, 1); - UNBLOCK_INPUT; - } - - { - RECT rt; - rt.left = rt.right = rt.top = rt.bottom = 0; - - BLOCK_INPUT; - AdjustWindowRect(&rt, f->output_data.w32->dwStyle, - FRAME_EXTERNAL_MENU_BAR (f)); - UNBLOCK_INPUT; - - pt.x += (rt.right - rt.left); - pt.y += (rt.bottom - rt.top); - } - /* Treat negative positions as relative to the leftmost bottommost position that fits on the screen. */ if (flags & XNegative) f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width - - 2 * f->border_width - pt.x - FRAME_PIXEL_WIDTH (f) + f->left_pos); if (flags & YNegative) f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height - - 2 * f->border_width - pt.y - FRAME_PIXEL_HEIGHT (f) + f->top_pos); /* The left_pos and top_pos @@ -5442,9 +5426,7 @@ x_check_fullscreen (f) x_fullscreen_adjust (f, &width, &height, &ign, &ign); /* We do not need to move the window, it shall be taken care of - when setting WM manager hints. - If the frame is visible already, the position is checked by - x_check_fullscreen_move. */ + when setting WM manager hints. */ if (FRAME_COLS (f) != width || FRAME_LINES (f) != height) { change_frame_size (f, height, width, 0, 1, 0); @@ -5457,36 +5439,6 @@ x_check_fullscreen (f) } } -/* If frame parameters are set after the frame is mapped, we need to move - the window. This is done in xfns.c. - Some window managers moves the window to the right position, some - moves the outer window manager window to the specified position. - Here we check that we are in the right spot. If not, make a second - move, assuming we are dealing with the second kind of window manager. */ -static void -x_check_fullscreen_move (f) - struct frame *f; -{ - if (f->want_fullscreen & FULLSCREEN_MOVE_WAIT) - { - int expect_top = f->top_pos; - int expect_left = f->left_pos; - - if (f->want_fullscreen & FULLSCREEN_HEIGHT) - expect_top = 0; - if (f->want_fullscreen & FULLSCREEN_WIDTH) - expect_left = 0; - - if (expect_top != f->top_pos - || expect_left != f->left_pos) - x_set_offset (f, expect_left, expect_top, 1); - - /* Just do this once */ - f->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT; - } -} - - /* Call this to change the size of frame F's x-window. If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity for this size change and subsequent size changes. @@ -6235,32 +6187,7 @@ w32_term_init (display_name, xrm_option, resource_name) horizontally reflected compared to how they appear on X, so we need to bitswap and convert to unsigned shorts before creating the bitmaps. */ - { - int i, j; - - for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++) - { - int h = fringe_bitmaps[i].height; - int wd = fringe_bitmaps[i].width; - unsigned short *w32bits - = (unsigned short *)alloca (h * sizeof (unsigned short)); - unsigned short *wb = w32bits; - unsigned char *bits = fringe_bitmaps[i].bits; - for (j = 0; j < h; j++) - { - static unsigned char swap_nibble[16] - = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */ - 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */ - 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */ - 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */ - - unsigned char b = *bits++; - *wb++ = (unsigned short)((swap_nibble[b & 0xf]<<4) - | (swap_nibble[(b>>4) & 0xf])); - } - fringe_bmp[i] = CreateBitmap (wd, h, 1, 1, w32bits); - } - } + w32_init_fringe (); #ifndef F_SETOWN_BUG #ifdef F_SETOWN @@ -6328,13 +6255,7 @@ x_delete_display (dpyinfo) xfree (dpyinfo->font_table); xfree (dpyinfo->w32_id_name); - /* Destroy row bitmaps. */ - { - int i; - - for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++) - DeleteObject (fringe_bmp[i]); - } + w32_reset_fringes (); } /* Set up use of W32. */ @@ -6365,6 +6286,8 @@ static struct redisplay_interface w32_redisplay_interface = w32_get_glyph_overhangs, x_fix_overlapping_area, w32_draw_fringe_bitmap, + w32_define_fringe_bitmap, + w32_destroy_fringe_bitmap, w32_per_char_metric, w32_encode_char, NULL, /* w32_compute_glyph_string_overhangs */ @@ -6413,6 +6336,12 @@ w32_initialize () w32_system_caret_x = 0; w32_system_caret_y = 0; + /* Initialize w32_use_visible_system_caret based on whether a screen + reader is in use. */ + if (!SystemParametersInfo (SPI_GETSCREENREADER, 0, + &w32_use_visible_system_caret, 0)) + w32_use_visible_system_caret = 0; + last_tool_bar_item = -1; any_help_event_p = 0; @@ -6457,6 +6386,8 @@ w32_initialize () /* Dynamically link to optional system components. */ { HANDLE user_lib = LoadLibrary ("user32.dll"); + UINT smoothing_type; + BOOL smoothing_enabled; #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn) @@ -6477,6 +6408,28 @@ w32_initialize () effectively form the border of the main scroll bar range. */ vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border = GetSystemMetrics (SM_CYVSCROLL); + + /* Constants that are not always defined by the system headers + since they only exist on certain versions of Windows. */ +#ifndef SPI_GETFONTSMOOTHING +#define SPI_GETFONTSMOOTHING 0x4A +#endif +#ifndef SPI_GETFONTSMOOTHINGTYPE +#define SPI_GETFONTSMOOTHINGTYPE 0x0200A +#endif +#ifndef FE_FONTSMOOTHINGCLEARTYPE +#define FE_FONTSMOOTHINGCLEARTYPE 0x2 +#endif + + /* Determine if Cleartype is in use. Used to enable a hack in + the char metric calculations which adds extra pixels to + compensate for the "sub-pixels" that are not counted by the + system APIs. */ + cleartype_active = + SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0) + && smoothing_enabled + && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0) + && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE; } } @@ -6493,9 +6446,9 @@ syms_of_w32term () Qvendor_specific_keysyms = intern ("vendor-specific-keysyms"); DEFVAR_INT ("w32-num-mouse-buttons", - &Vw32_num_mouse_buttons, + &w32_num_mouse_buttons, doc: /* Number of physical mouse buttons. */); - Vw32_num_mouse_buttons = Qnil; + w32_num_mouse_buttons = 2; DEFVAR_LISP ("w32-swap-mouse-buttons", &Vw32_swap_mouse_buttons, @@ -6546,11 +6499,19 @@ software is running as it starts up. When this variable is set, other variables affecting the appearance of the cursor have no effect. */); - /* Initialize w32_use_visible_system_caret based on whether a screen - reader is in use. */ - if (!SystemParametersInfo (SPI_GETSCREENREADER, 0, - &w32_use_visible_system_caret, 0)) - w32_use_visible_system_caret = 0; + w32_use_visible_system_caret = 0; + + /* We don't yet support this, but defining this here avoids whining + from cus-start.el and other places, like "M-x set-variable". */ + DEFVAR_BOOL ("x-use-underline-position-properties", + &x_use_underline_position_properties, + doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. +nil means ignore them. If you encounter fonts with bogus +UNDERLINE_POSITION font properties, for example 7x13 on XFree prior +to 4.1, set this to nil. + +NOTE: Not supported on MS-Windows yet. */); + x_use_underline_position_properties = 0; DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, doc: /* If not nil, Emacs uses toolkit scroll bars. */); @@ -6559,3 +6520,6 @@ the cursor have no effect. */); staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; } + +/* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646 + (do not change this comment) */