X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9f5a911b46577a2d573794ded1bd883685e901da..8030369ccb5c871d3ce11b96c220f318bc741ed8:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index 1fe99c75ac..c9628277a4 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -62,11 +62,11 @@ Boston, MA 02111-1307, USA. */ #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER)) -/* Bitmaps for truncated lines. */ +/* Fringe bitmaps. */ -enum bitmap_type +enum fringe_bitmap_type { - NO_BITMAP, + NO_FRINGE_BITMAP, LEFT_TRUNCATION_BITMAP, RIGHT_TRUNCATION_BITMAP, OVERLAY_ARROW_BITMAP, @@ -84,9 +84,17 @@ enum bitmap_type `indicate-empty-lines' is non-nil. */ #define zv_width 8 -#define zv_height 8 +#define zv_height 72 +#define zv_period 3 static unsigned short zv_bits[] = { - 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00}; + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00}; static HBITMAP zv_bmp; /* An arrow like this: `<-'. */ @@ -162,6 +170,10 @@ static Lisp_Object previous_help_echo; static int any_help_event_p; +/* Non-zero means autoselect window with the mouse cursor. */ + +int mouse_autoselect_window; + /* Non-zero means draw block and hollow cursor as wide as the glyph under it. For example, if a block cursor is over a tab, it will be drawn as wide as that tab on the display. */ @@ -176,8 +188,6 @@ extern unsigned int msh_mousewheel; extern void free_frame_menubar (); -extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags); - extern int w32_codepage_for_font (char *fontname); extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp, @@ -214,6 +224,13 @@ struct frame *pending_autoraise_frame; struct cursor_pos output_cursor; +/* The handle of the frame that currently owns the system caret. */ +HWND w32_system_caret_hwnd; +int w32_system_caret_height; +int w32_system_caret_x; +int w32_system_caret_y; +int w32_use_visible_system_caret; + /* Flag to enable Unicode output in case users wish to use programs like Twinbridge on '95 rather than installed system level support for Far East languages. */ @@ -316,7 +333,7 @@ extern int errno; /* A mask of extra modifier bits to put into every keyboard char. */ -extern int extra_keyboard_modifiers; +extern EMACS_INT extra_keyboard_modifiers; /* Enumeration for overriding/changing the face to use for drawing glyphs in x_draw_glyphs. */ @@ -375,12 +392,13 @@ static void x_clear_frame P_ ((void)); static void x_clear_cursor P_ ((struct window *)); static void frame_highlight P_ ((struct frame *)); static void frame_unhighlight P_ ((struct frame *)); -static void w32_new_focus_frame P_ ((struct w32_display_info *, - struct frame *)); +static void x_new_focus_frame P_ ((struct w32_display_info *, + struct frame *)); 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)); +static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int, + enum text_cursor_kinds)); static void expose_frame P_ ((struct frame *, int, int, int, int)); static int expose_window_tree P_ ((struct window *, RECT *)); static int expose_window P_ ((struct window *, RECT *)); @@ -394,13 +412,17 @@ static void x_update_window_cursor P_ ((struct window *, int)); static void x_erase_phys_cursor P_ ((struct window *)); void x_display_cursor P_ ((struct window *w, int, int, int, int, int)); void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int)); -static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *, - enum bitmap_type)); +static void w32_draw_fringe_bitmap P_ ((struct window *, HDC hdc, + struct glyph_row *, + enum fringe_bitmap_type, int left_p)); static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, HDC, int)); static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *)); -static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *)); -static void note_overwritten_text_cursor P_ ((struct window *, int, int)); +static void x_draw_row_fringe_bitmaps P_ ((struct window *, + struct glyph_row *)); +static void notice_overwritten_cursor P_ ((struct window *, + enum glyph_row_area, + int, int, int, int)); static Lisp_Object Qvendor_specific_keysyms; @@ -576,6 +598,10 @@ x_update_window_begin (w) struct frame *f = XFRAME (WINDOW_FRAME (w)); struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f); + /* Hide the system caret during an update. */ + if (w32_use_visible_system_caret) + SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0); + updated_window = w; set_output_cursor (&w->cursor); @@ -643,7 +669,7 @@ x_draw_vertical_border (w) window_box_edges (w, -1, (int *) &r.left, (int *) &r.top, (int *) &r.right, (int *) &r.bottom); - r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f); + r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f); r.right = r.left + 1; r.bottom -= 1; @@ -697,6 +723,12 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) dpyinfo->mouse_face_window = Qnil; } + /* Unhide the caret. This won't actually show the cursor, unless it + was visible before the corresponding call to HideCaret in + x_update_window_begin. */ + if (w32_use_visible_system_caret) + SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0); + updated_window = NULL; } @@ -743,9 +775,9 @@ w32_frame_up_to_date (f) /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay - arrow bitmaps, or clear the areas where they would be displayed + arrow bitmaps, or clear the fringes if no bitmaps are required before DESIRED_ROW is made current. The window being updated is - found in updated_window. This function It is called from + found in updated_window. This function is called from update_window_line only if it is known that there are differences between bitmaps to be drawn between current row and DESIRED_ROW. */ @@ -754,55 +786,69 @@ x_after_update_window_line (desired_row) struct glyph_row *desired_row; { struct window *w = updated_window; - + struct frame *f; + int width, height; + xassert (w); if (!desired_row->mode_line_p && !w->pseudo_window_p) { - struct frame *f; - int width; + BLOCK_INPUT; + x_draw_row_fringe_bitmaps (w, desired_row); + UNBLOCK_INPUT; + } + + /* When a window has disappeared, make sure that no rest of + full-width rows stays visible in the internal border. Could + check here if updated_window is the leftmost/rightmost window, + but I guess it's not worth doing since vertically split windows + are almost never used, internal border is rarely set, and the + overhead is very small. */ + if (windows_or_buffers_changed + && desired_row->full_width_p + && (f = XFRAME (w->frame), + width = FRAME_INTERNAL_BORDER_WIDTH (f), + width != 0) + && (height = desired_row->visible_height, + height > 0)) + { + int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); + /* Internal border is drawn below the tool bar. */ + if (WINDOWP (f->tool_bar_window) + && w == XWINDOW (f->tool_bar_window)) + y -= width; BLOCK_INPUT; - x_draw_row_bitmaps (w, desired_row); - - /* When a window has disappeared, make sure that no rest of - full-width rows stays visible in the internal border. */ - if (windows_or_buffers_changed - && (f = XFRAME (w->frame), - width = FRAME_INTERNAL_BORDER_WIDTH (f), - width != 0)) - { - int height = desired_row->visible_height; - int x = (window_box_right (w, -1) - + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)); - int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); - HDC hdc = get_frame_dc (f); - - w32_clear_area (f, hdc, x, y, width, height); - release_frame_dc (f, hdc); - } - + { + HDC hdc = get_frame_dc (f); + w32_clear_area (f, hdc, 0, y, width, height); + w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width, + y, width, height); + release_frame_dc (f, hdc); + } UNBLOCK_INPUT; } } -/* Draw the bitmap WHICH in one of the areas to the left or right of +/* Draw the bitmap WHICH in one of the left or right fringes of window W. ROW is the glyph row for which to display the bitmap; it determines the vertical position at which the bitmap has to be drawn. */ static void -w32_draw_bitmap (w, hdc, row, which) +w32_draw_fringe_bitmap (w, hdc, row, which, left_p) struct window *w; HDC hdc; struct glyph_row *row; - enum bitmap_type which; + enum fringe_bitmap_type which; + int left_p; { struct frame *f = XFRAME (WINDOW_FRAME (w)); Window window = FRAME_W32_WINDOW (f); HDC compat_hdc; int x, y, wd, h, dy; + int b1, b2; HBITMAP pixmap; HANDLE horig_obj; struct face *face; @@ -810,71 +856,118 @@ w32_draw_bitmap (w, hdc, row, which) /* Must clip because of partially visible lines. */ w32_clip_to_row (w, row, hdc, 1); + /* Convert row to frame coordinates. */ + y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + switch (which) { + case NO_FRINGE_BITMAP: + wd = 0; + h = 0; + break; + case LEFT_TRUNCATION_BITMAP: wd = left_width; h = left_height; pixmap = left_bmp; - x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) - - wd - - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2); break; case OVERLAY_ARROW_BITMAP: wd = ov_width; h = ov_height; pixmap = ov_bmp; - x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) - - wd - - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2); break; case RIGHT_TRUNCATION_BITMAP: wd = right_width; h = right_height; pixmap = right_bmp; - x = window_box_right (w, -1); - x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2; break; case CONTINUED_LINE_BITMAP: wd = continued_width; h = continued_height; pixmap = continued_bmp; - x = window_box_right (w, -1); - x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2; break; case CONTINUATION_LINE_BITMAP: wd = continuation_width; h = continuation_height; pixmap = continuation_bmp; - x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) - - wd - - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2); break; case ZV_LINE_BITMAP: wd = zv_width; - h = zv_height; + h = zv_height - (y % zv_period); pixmap = zv_bmp; - x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) - - wd - - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2); break; default: abort (); } - /* Convert to frame coordinates. Set dy to the offset in the row to - start drawing the bitmap. */ - y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + /* Clip bitmap if too high. */ + if (h > row->height) + h = row->height; + + /* Set dy to the offset in the row to start drawing the bitmap. */ dy = (row->height - h) / 2; /* Draw the bitmap. */ - face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID); + face = FACE_FROM_ID (f, FRINGE_FACE_ID); + PREPARE_FACE_FOR_DISPLAY (f, face); + + /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill + the fringe. */ + b1 = -1; + if (left_p) + { + if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f)) + wd = FRAME_X_LEFT_FRINGE_WIDTH (f); + x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) + - wd + - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2); + if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h) + { + /* If W has a vertical border to its left, don't draw over it. */ + int border = ((XFASTINT (w->left) > 0 + && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) + ? 1 : 0); + b1 = (window_box_left (w, -1) + - FRAME_X_LEFT_FRINGE_WIDTH (f) + + border); + b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border); + } + } + else + { + if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f)) + wd = FRAME_X_RIGHT_FRINGE_WIDTH (f); + x = (window_box_right (w, -1) + + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2); + /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill + the fringe. */ + if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h) + { + b1 = window_box_right (w, -1); + b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f); + } + } + + if (b1 >= 0) + { + int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); + + w32_fill_area (f, hdc, face->background, + b1, + WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, + row->y)), + b2, + row->visible_height); + } + + if (which == NO_FRINGE_BITMAP) + return; compat_hdc = CreateCompatibleDC (hdc); SaveDC (hdc); @@ -883,7 +976,9 @@ w32_draw_bitmap (w, hdc, row, which) SetTextColor (hdc, face->background); SetBkColor (hdc, face->foreground); - BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY); + BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, + (which == ZV_LINE_BITMAP ? (row->y % zv_period) : 0), + SRCCOPY); SelectObject (compat_hdc, horig_obj); DeleteDC (compat_hdc); @@ -891,18 +986,16 @@ w32_draw_bitmap (w, hdc, row, which) } -/* Draw flags bitmaps for glyph row ROW on window W. Call this +/* Draw fringe bitmaps for glyph row ROW on window W. Call this function with input blocked. */ static void -x_draw_row_bitmaps (w, row) +x_draw_row_fringe_bitmaps (w, row) struct window *w; struct glyph_row *row; { struct frame *f = XFRAME (w->frame); - enum bitmap_type bitmap; - struct face *face; - int header_line_height = -1; + enum fringe_bitmap_type bitmap; HDC hdc; xassert (interrupt_input_blocked); @@ -912,81 +1005,40 @@ x_draw_row_bitmaps (w, row) if (row->visible_height <= 0) return; - face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID); - PREPARE_FACE_FOR_DISPLAY (f, face); - - /* Decide which bitmap to draw at the left side. */ - if (row->overlay_arrow_p) - bitmap = OVERLAY_ARROW_BITMAP; - else if (row->truncated_on_left_p) - bitmap = LEFT_TRUNCATION_BITMAP; - else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) - bitmap = CONTINUATION_LINE_BITMAP; - else if (row->indicate_empty_line_p) - bitmap = ZV_LINE_BITMAP; - else - bitmap = NO_BITMAP; - hdc = get_frame_dc (f); - /* Clear flags area if no bitmap to draw or if bitmap doesn't fill - the flags area. */ - if (bitmap == NO_BITMAP - || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f)) - { - /* If W has a vertical border to its left, don't draw over it. */ - int border = ((XFASTINT (w->left) > 0 - && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) - ? 1 : 0); - int left = window_box_left (w, -1); + if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0) + { + /* Decide which bitmap to draw in the left fringe. */ + if (row->overlay_arrow_p) + bitmap = OVERLAY_ARROW_BITMAP; + else if (row->truncated_on_left_p) + bitmap = LEFT_TRUNCATION_BITMAP; + else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) + bitmap = CONTINUATION_LINE_BITMAP; + else if (row->indicate_empty_line_p) + bitmap = ZV_LINE_BITMAP; + else + bitmap = NO_FRINGE_BITMAP; - if (header_line_height < 0) - header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); - - w32_fill_area (f, hdc, face->background, - left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border, - WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, - row->y)), - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border, - row->visible_height); + w32_draw_fringe_bitmap (w, hdc, row, bitmap, 1); } - /* Draw the left bitmap. */ - if (bitmap != NO_BITMAP) - w32_draw_bitmap (w, hdc, row, bitmap); - - /* Decide which bitmap to draw at the right side. */ - if (row->truncated_on_right_p) - bitmap = RIGHT_TRUNCATION_BITMAP; - else if (row->continued_p) - bitmap = CONTINUED_LINE_BITMAP; - else - bitmap = NO_BITMAP; - - /* Clear flags area if no bitmap to draw of if bitmap doesn't fill - the flags area. */ - if (bitmap == NO_BITMAP - || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f)) + if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0) { - int right = window_box_right (w, -1); - - if (header_line_height < 0) - header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); + /* Decide which bitmap to draw in the right fringe. */ + if (row->truncated_on_right_p) + bitmap = RIGHT_TRUNCATION_BITMAP; + else if (row->continued_p) + bitmap = CONTINUED_LINE_BITMAP; + else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0) + bitmap = ZV_LINE_BITMAP; + else + bitmap = NO_FRINGE_BITMAP; - w32_fill_area (f, hdc, face->background, - right, - WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, - row->y)), - FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f), - row->visible_height); + w32_draw_fringe_bitmap (w, hdc, row, bitmap, 0); } - /* Draw the right bitmap. */ - if (bitmap != NO_BITMAP) - w32_draw_bitmap (w, hdc, row, bitmap); - release_frame_dc (f, hdc); } @@ -1173,9 +1225,24 @@ w32_native_per_char_metric (font, char2b, font_type, pcm) if (retval) { +#if 0 + /* Disabled until we can find a way to get the right results + on all versions of Windows. */ + + /* Don't trust the ABC widths. For synthesized fonts they are + wrong, and so is the result of GetCharWidth()! */ + int real_width; + GetCharWidth (hdc, *char2b, *char2b, &real_width); +#endif 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 + ExtTextOut will do with the broken font. */ + if (pcm->width != real_width) + pcm->width = (pcm->width + real_width) / 2; +#endif pcm->lbearing = char_widths.abcA; - pcm->rbearing = pcm->width - char_widths.abcC; + pcm->rbearing = char_widths.abcA + char_widths.abcB; pcm->ascent = FONT_BASE (font); pcm->descent = FONT_DESCENT (font); } @@ -1778,7 +1845,7 @@ x_append_stretch_glyph (it, object, width, height, ascent) 4. `:height HEIGHT' specifies that the height of the stretch produced should be HEIGHT, measured in canonical character units. - 5. `:relative-height FACTOR' specifies that the height of the the + 5. `:relative-height FACTOR' specifies that the height of the stretch should be FACTOR times the height of the characters having the glyph property. @@ -2669,7 +2736,8 @@ struct glyph_string /* Encapsulate the different ways of displaying text under W32. */ -void W32_TEXTOUT (s, x, y,chars,nchars) +static void +w32_text_out (s, x, y,chars,nchars) struct glyph_string * s; int x, y; wchar_t * chars; @@ -2683,8 +2751,8 @@ void W32_TEXTOUT (s, x, y,chars,nchars) else if (s->first_glyph->w32_font_type == UNICODE_FONT) ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL); else - ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars, - nchars * charset_dim, NULL); + ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars, + nchars * charset_dim, NULL); } #if GLYPH_DEBUG @@ -2735,7 +2803,7 @@ static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc, enum draw_glyphs_face)); static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *, enum glyph_row_area, int, int, - enum draw_glyphs_face, int *, int *, int)); + enum draw_glyphs_face, int)); 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 *, @@ -3417,7 +3485,7 @@ x_draw_glyph_string_foreground (s) char1b[i] = BYTE2 (s->char2b[i]); /* Draw text with TextOut and friends. */ - W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars); + w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars); } if (s->font && s->font->hfont) SelectObject (s->hdc, old_font); @@ -3464,7 +3532,7 @@ x_draw_composite_glyph_string_foreground (s) else { for (i = 0; i < s->nchars; i++, ++s->gidx) - W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2], + w32_text_out (s, x + s->cmp->offsets[s->gidx * 2], s->ybase - s->cmp->offsets[s->gidx * 2 + 1], s->char2b + i, 1); } @@ -3612,6 +3680,10 @@ x_setup_relief_colors (s) if (s->face->use_box_color_for_shadows_p) color = s->face->box_color; + else if (s->first_glyph->type == IMAGE_GLYPH + && s->img->pixmap + && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) + color = IMAGE_BACKGROUND (s->img, s->f, 0); else color = s->gc->background; @@ -3657,14 +3729,14 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, for (i = 0; i < width; ++i) w32_fill_area (f, hdc, gc.foreground, left_x + i * left_p, top_y + i, - (right_x + 1 - i * right_p) - (left_x + i * left_p), 1); + right_x - left_x - i * (left_p + right_p ) + 1, 1); /* Left. */ if (left_p) for (i = 0; i < width; ++i) w32_fill_area (f, hdc, gc.foreground, left_x + i, top_y + i, 1, - (bottom_y - i + 1) - (top_y + i)); + bottom_y - top_y - 2 * i + 1); if (raised_p) gc.foreground = f->output_data.w32->black_relief.gc->foreground; @@ -3675,14 +3747,14 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, for (i = 0; i < width; ++i) w32_fill_area (f, hdc, gc.foreground, left_x + i * left_p, bottom_y - i, - (right_x + 2 - i * right_p) - (left_x + i * left_p), 1); + right_x - left_x - i * (left_p + right_p) + 1, 1); /* Right. */ if (right_p) for (i = 0; i < width; ++i) w32_fill_area (f, hdc, gc.foreground, right_x - i, top_y + i + 1, 1, - (bottom_y - i) - (top_y + i + 1)); + bottom_y - top_y - 2 * i - 1); w32_set_clip_rectangle (hdc, NULL); @@ -3747,7 +3819,7 @@ x_draw_glyph_string_box (s) if (s->row->full_width_p && !s->w->pseudo_window_p) { - last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f); + last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f); if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f)) last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f); } @@ -3875,8 +3947,12 @@ x_draw_image_foreground (s) the image. I believe it's looking better if we do nothing here for mouse-face. */ if (s->hl == DRAW_CURSOR) - w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1, - s->img->height - 1); + { + 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); + } w32_set_clip_rectangle (s->hdc, NULL); } } @@ -3916,7 +3992,7 @@ x_draw_image_relief (s) if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) { - thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3; + thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF; raised_p = s->hl == DRAW_IMAGE_RAISED; } else @@ -4016,8 +4092,12 @@ w32_draw_image_foreground_1 (s, pixmap) the image. I believe it's looking better if we do nothing here for mouse-face. */ if (s->hl == DRAW_CURSOR) - w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1, - s->img->height - 1); + { + 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); + } } } else @@ -4640,7 +4720,9 @@ x_set_glyph_string_background_width (s, start, last_x) || s->face->background != default_face->background || s->face->stipple != default_face->stipple || s->row->mouse_face_p)) - || s->hl == DRAW_MOUSE_FACE)) + || s->hl == DRAW_MOUSE_FACE + || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) + && s->row->fill_line_p))) s->extends_to_end_of_line_p = 1; /* If S extends its face to the end of the line, set its @@ -4842,27 +4924,19 @@ x_set_glyph_string_background_width (s, start, last_x) DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it DRAW_IMAGE_RAISED draw an image with a raised relief around it - If REAL_START is non-null, return in *REAL_START the real starting - position for display. This can be different from START in case - overlapping glyphs must be displayed. If REAL_END is non-null, - return in *REAL_END the real end position for display. This can be - different from END in case overlapping glyphs must be displayed. - If OVERLAPS_P is non-zero, draw only the foreground of characters and clip to the physical height of ROW. Value is the x-position reached, relative to AREA of W. */ static int -x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, - overlaps_p) +x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) struct window *w; int x; struct glyph_row *row; enum glyph_row_area area; int start, end; enum draw_glyphs_face hl; - int *real_start, *real_end; int overlaps_p; { struct glyph_string *head, *tail; @@ -4876,19 +4950,14 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, end = min (end, row->used[area]); start = max (0, start); start = min (end, start); - if (real_start) - *real_start = start; - if (real_end) - *real_end = end; /* Translate X to frame coordinates. Set last_x to the right end of the drawing area. */ if (row->full_width_p) { /* X is relative to the left edge of W, without scroll bars - or flag areas. */ + or fringes. */ struct frame *f = XFRAME (WINDOW_FRAME (w)); - /* int width = FRAME_FLAGS_AREA_WIDTH (f); */ int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f); x += window_left_x; @@ -4951,8 +5020,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, DRAW_NORMAL_TEXT, dummy_x, last_x, overlaps_p); start = i; - if (real_start) - *real_start = start; x_compute_overhangs_and_x (t, head->x, 1); x_prepend_glyph_string_lists (&head, &tail, h, t); } @@ -4972,8 +5039,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, overlaps_p); for (s = h; s; s = s->next) s->background_filled_p = 1; - if (real_start) - *real_start = i; x_compute_overhangs_and_x (t, head->x, 1); x_prepend_glyph_string_lists (&head, &tail, h, t); } @@ -4990,8 +5055,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, overlaps_p); x_compute_overhangs_and_x (h, tail->x + tail->width, 0); x_append_glyph_string_lists (&head, &tail, h, t); - if (real_end) - *real_end = i; } /* Append glyph strings for glyphs following the last glyph @@ -5009,8 +5072,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, s->background_filled_p = 1; x_compute_overhangs_and_x (h, tail->x + tail->width, 0); x_append_glyph_string_lists (&head, &tail, h, t); - if (real_end) - *real_end = i; } } @@ -5018,6 +5079,30 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, for (s = head; s; s = s->next) x_draw_glyph_string (s); + if (area == TEXT_AREA + && !row->full_width_p + /* When drawing overlapping rows, only the glyph strings' + foreground is drawn, which doesn't erase a cursor + completely. */ + && !overlaps_p) + { + int x0 = head ? head->x : x; + int x1 = tail ? tail->x + tail->background_width : x; + + x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0); + x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1); + + if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0) + { + int left_area_width = window_box_width (w, LEFT_MARGIN_AREA); + x0 -= left_area_width; + x1 -= left_area_width; + } + + notice_overwritten_cursor (w, area, x0, x1, + row->y, MATRIX_ROW_BOTTOM_Y (row)); + } + /* Value is the x-position up to which drawn, relative to AREA of W. This doesn't include parts drawn because of overhangs. */ x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached); @@ -5070,8 +5155,7 @@ x_fix_overlapping_area (w, row, area) && row->glyphs[area][i].overlaps_vertically_p); x_draw_glyphs (w, start_x, row, area, start, i, - DRAW_NORMAL_TEXT, - NULL, NULL, 1); + DRAW_NORMAL_TEXT, 1); } else { @@ -5095,7 +5179,7 @@ x_write_glyphs (start, len) struct glyph *start; int len; { - int x, hpos, real_start, real_end; + int x, hpos; xassert (updated_window && updated_row); BLOCK_INPUT; @@ -5106,12 +5190,7 @@ x_write_glyphs (start, len) x = x_draw_glyphs (updated_window, output_cursor.x, updated_row, updated_area, hpos, hpos + len, - DRAW_NORMAL_TEXT, - &real_start, &real_end, 0); - - /* If we drew over the cursor, note that it is not visible any more. */ - note_overwritten_text_cursor (updated_window, real_start, - real_end - real_start); + DRAW_NORMAL_TEXT, 0); UNBLOCK_INPUT; @@ -5133,7 +5212,7 @@ x_insert_glyphs (start, len) int line_height, shift_by_width, shifted_region_width; struct glyph_row *row; struct glyph *glyph; - int frame_x, frame_y, hpos, real_start, real_end; + int frame_x, frame_y, hpos; HDC hdc; xassert (updated_window && updated_row); @@ -5166,9 +5245,8 @@ x_insert_glyphs (start, len) /* Write the glyphs. */ hpos = start - row->glyphs[updated_area]; x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len, - DRAW_NORMAL_TEXT, &real_start, &real_end, 0); - note_overwritten_text_cursor (w, real_start, real_end - real_start); - + DRAW_NORMAL_TEXT, 0); + /* Advance the output cursor. */ output_cursor.hpos += len; output_cursor.x += shift_by_width; @@ -5242,10 +5320,13 @@ x_clear_end_of_line (to_x) /* Notice if the cursor will be cleared by this operation. */ if (!updated_row->full_width_p) - note_overwritten_text_cursor (w, output_cursor.hpos, -1); + notice_overwritten_cursor (w, updated_area, + output_cursor.x, -1, + updated_row->y, + MATRIX_ROW_BOTTOM_Y (updated_row)); from_x = output_cursor.x; - + /* Translate to frame coordinates. */ if (updated_row->full_width_p) { @@ -5390,14 +5471,15 @@ x_scroll_run (w, run) { struct frame *f = XFRAME (w->frame); int x, y, width, height, from_y, to_y, bottom_y; - HDC hdc = get_frame_dc (f); + HWND hwnd = FRAME_W32_WINDOW (f); + HRGN expect_dirty; /* Get frame-relative bounding box of the text display area of W, - without mode lines. Include in this box the flags areas to the - left and right of W. */ + without mode lines. Include in this box the left and right + fringes of W. */ window_box (w, -1, &x, &y, &width, &height); - width += FRAME_X_FLAGS_AREA_WIDTH (f); - x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f); + width += FRAME_X_FRINGE_WIDTH (f); + x -= FRAME_X_LEFT_FRINGE_WIDTH (f); from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y); to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y); @@ -5411,6 +5493,7 @@ x_scroll_run (w, run) height = bottom_y - from_y; else height = run->height; + expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y); } else { @@ -5420,6 +5503,7 @@ x_scroll_run (w, run) height = bottom_y - to_y; else height = run->height; + expect_dirty = CreateRectRgn (x, y, x + width, to_y); } BLOCK_INPUT; @@ -5428,10 +5512,32 @@ x_scroll_run (w, run) updated_window = w; x_clear_cursor (w); - BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY); - + { + RECT from; + RECT to; + HRGN dirty = CreateRectRgn (0, 0, 0, 0); + HRGN combined = CreateRectRgn (0, 0, 0, 0); + + from.left = to.left = x; + from.right = to.right = x + width; + from.top = from_y; + from.bottom = from_y + height; + to.top = y; + to.bottom = bottom_y; + + ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty, + NULL, SW_INVALIDATE); + + /* Combine this with what we expect to be dirty. This covers the + case where not all of the region we expect is actually dirty. */ + CombineRgn (combined, dirty, expect_dirty, RGN_OR); + + /* If the dirty region is not what we expected, redraw the entire frame. */ + if (!EqualRgn (combined, expect_dirty)) + SET_FRAME_GARBAGED (f); + } + UNBLOCK_INPUT; - release_frame_dc (f, hdc); } @@ -5568,8 +5674,7 @@ expose_area (w, row, r, area) /* If row extends face to end of line write the whole line. */ x_draw_glyphs (w, 0, row, area, 0, row->used[area], - DRAW_NORMAL_TEXT, - NULL, NULL, 0); + DRAW_NORMAL_TEXT, 0); else { /* Set START_X to the window-relative start position for drawing glyphs of @@ -5607,8 +5712,7 @@ expose_area (w, row, r, area) x_draw_glyphs (w, first_x - start_x, row, area, first - row->glyphs[area], last - row->glyphs[area], - DRAW_NORMAL_TEXT, - NULL, NULL, 0); + DRAW_NORMAL_TEXT, 0); } } @@ -5627,7 +5731,7 @@ expose_line (w, row, r) if (row->mode_line_p || w->pseudo_window_p) x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA], - DRAW_NORMAL_TEXT, NULL, NULL, 0); + DRAW_NORMAL_TEXT, 0); else { if (row->used[LEFT_MARGIN_AREA]) @@ -5636,7 +5740,7 @@ expose_line (w, row, r) expose_area (w, row, r, TEXT_AREA); if (row->used[RIGHT_MARGIN_AREA]) expose_area (w, row, r, RIGHT_MARGIN_AREA); - x_draw_row_bitmaps (w, row); + x_draw_row_fringe_bitmaps (w, row); } return row->mouse_face_p; @@ -5997,9 +6101,13 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y) return success_p; } +/* Parse a button MESSAGE. The button index is returned in PBUTTON, and + the state in PUP. XBUTTON provides extra information for extended mouse + button messages. Returns FALSE if unable to parse the message. */ BOOL -parse_button (message, pbutton, pup) +parse_button (message, xbutton, pbutton, pup) int message; + int xbutton; int * pbutton; int * pup; { @@ -6044,6 +6152,14 @@ parse_button (message, pbutton, pup) button = 1; up = 1; break; + case WM_XBUTTONDOWN: + button = xbutton + 2; + up = 0; + break; + case WM_XBUTTONUP: + button = xbutton + 2; + up = 1; + break; default: return (FALSE); } @@ -6069,11 +6185,12 @@ construct_mouse_click (result, msg, f) int button; int up; - parse_button (msg->msg.message, &button, &up); + parse_button (msg->msg.message, HIWORD (msg->msg.wParam), + &button, &up); - /* Make the event type no_event; we'll change that when we decide + /* Make the event type NO_EVENT; we'll change that when we decide otherwise. */ - result->kind = mouse_click; + result->kind = MOUSE_CLICK_EVENT; result->code = button; result->timestamp = msg->msg.time; result->modifiers = (msg->dwModifiers @@ -6095,7 +6212,7 @@ construct_mouse_wheel (result, msg, f) struct frame *f; { POINT p; - result->kind = mouse_wheel; + result->kind = MOUSE_WHEEL_EVENT; result->code = (short) HIWORD (msg->msg.wParam); result->timestamp = msg->msg.time; result->modifiers = msg->dwModifiers; @@ -6123,7 +6240,7 @@ construct_drag_n_drop (result, msg, f) char *name; int i, len; - result->kind = drag_n_drop; + result->kind = DRAG_N_DROP_EVENT; result->code = 0; result->timestamp = msg->msg.time; result->modifiers = msg->dwModifiers; @@ -6150,7 +6267,7 @@ construct_drag_n_drop (result, msg, f) continue; name = alloca (len + 1); DragQueryFile (hdrop, i, name, len + 1); - files = Fcons (build_string (name), files); + files = Fcons (DECODE_FILE (build_string (name)), files); } DragFinish (hdrop); @@ -6187,6 +6304,28 @@ note_mouse_movement (frame, msg) memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event)); XSETFRAME (last_mouse_motion_frame, frame); +#if 0 /* Calling Lisp asynchronously is not safe. */ + if (mouse_autoselect_window) + { + int area; + Lisp_Object window; + static Lisp_Object last_window; + + window = window_from_coordinates (frame, mouse_x, mouse_y, &area, 0); + + /* Window will be selected only when it is not selected now and + last mouse movement event was not in it. Minibuffer window + will be selected iff it is active. */ + if (!EQ (window, last_window) + && !EQ (window, selected_window) + && (!MINI_WINDOW_P (XWINDOW (window)) + || (EQ (window, minibuf_window) && minibuf_level > 0))) + Fselect_window (window); + + last_window=window; + } +#endif + if (msg->hwnd != FRAME_W32_WINDOW (frame)) { frame->mouse_moved = 1; @@ -6211,11 +6350,6 @@ note_mouse_movement (frame, msg) } } -/* This is used for debugging, to turn off note_mouse_highlight. */ - -int disable_mouse_highlight; - - /************************************************************************ Mouse Face @@ -6335,7 +6469,7 @@ frame_to_window_pixel_xy (w, x, y) /* Take proper action when mouse has moved to the mode or header line of window W, x-position X. MODE_LINE_P non-zero means mouse is on the mode line. X is relative to the start of the text display area of - W, so the width of bitmap areas and scroll bars must be subtracted + W, so the width of fringes and scroll bars must be subtracted to get a position relative to the start of the mode line. */ static void @@ -6363,7 +6497,7 @@ note_mode_line_highlight (w, x, mode_line_p) glyph = row->glyphs[TEXT_AREA]; end = glyph + row->used[TEXT_AREA]; x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f) - + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)); + + FRAME_X_LEFT_FRINGE_WIDTH (f)); while (glyph < end && x >= x0 + glyph->pixel_width) @@ -6374,9 +6508,9 @@ note_mode_line_highlight (w, x, mode_line_p) if (glyph < end && STRINGP (glyph->object) - && XSTRING (glyph->object)->intervals + && STRING_INTERVALS (glyph->object) && glyph->charpos >= 0 - && glyph->charpos < XSTRING (glyph->object)->size) + && glyph->charpos < SCHARS (glyph->object)) { /* If we're on a string with `help-echo' text property, arrange for the help to be displayed. This is done by @@ -6432,7 +6566,7 @@ note_mouse_highlight (f, x, y) if (popup_activated ()) return; - if (disable_mouse_highlight + if (NILP (Vmouse_highlight) || !f->glyphs_initialized_p) return; @@ -6460,6 +6594,9 @@ note_mouse_highlight (f, x, y) if (!WINDOWP (window)) return; + /* Reset help_echo. It will get recomputed below. */ + help_echo = Qnil; + /* Convert to window-relative pixel coordinates. */ w = XWINDOW (window); frame_to_window_pixel_xy (w, &x, &y); @@ -6692,7 +6829,7 @@ note_mouse_highlight (f, x, y) if (NILP (b)) b = make_number (0); if (NILP (e)) - e = make_number (XSTRING (object)->size - 1); + e = make_number (SCHARS (object) - 1); fast_find_string_pos (w, XINT (b), object, &dpyinfo->mouse_face_beg_col, &dpyinfo->mouse_face_beg_row, @@ -6728,7 +6865,7 @@ note_mouse_highlight (f, x, y) { Lisp_Object before = Foverlay_start (overlay); Lisp_Object after = Foverlay_end (overlay); - Lisp_Object ignore; + int ignore; /* Note that we might not be able to find position BEFORE in the glyph matrix if the overlay is @@ -6790,7 +6927,7 @@ note_mouse_highlight (f, x, y) /* Try text properties. */ if (STRINGP (object) && charpos >= 0 - && charpos < XSTRING (object)->size) + && charpos < SCHARS (object)) { help = Fget_text_property (make_number (charpos), Qhelp_echo, object); @@ -6938,7 +7075,7 @@ w32_handle_tool_bar_click (f, button_event) if (NILP (enabled_p)) return; - if (button_event->kind == mouse_click) + if (button_event->modifiers & down_modifier) { /* Show item in pressed state. */ show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); @@ -6965,7 +7102,8 @@ w32_handle_tool_bar_click (f, button_event) event.kind = TOOL_BAR_EVENT; event.frame_or_window = frame; event.arg = key; - event.modifiers = button_event->modifiers; + /* The keyboard buffer doesn't like the up modifier being set. */ + event.modifiers = button_event->modifiers & ~up_modifier; kbd_buffer_store_event (&event); last_tool_bar_item = -1; } @@ -7092,7 +7230,7 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop) int i, past_end = 0; first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); - row = row_containing_pos (w, charpos, first, NULL); + row = row_containing_pos (w, charpos, first, NULL, 0); if (row == NULL) { if (charpos < MATRIX_ROW_START_CHARPOS (first)) @@ -7242,7 +7380,7 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop) #endif /* not 0 */ -/* Find the position of the the glyph for position POS in OBJECT in +/* Find the position of the glyph for position POS in OBJECT in window W's current matrix, and return in *X/*Y the pixel coordinates, and return in *HPOS/*VPOS the column/row of the glyph. @@ -7334,81 +7472,61 @@ show_mouse_face (dpyinfo, draw) { struct window *w = XWINDOW (dpyinfo->mouse_face_window); struct frame *f = XFRAME (WINDOW_FRAME (w)); - int i; - int cursor_off_p = 0; - struct cursor_pos saved_cursor; - - saved_cursor = output_cursor; - /* If window is in the process of being destroyed, don't bother - to do anything. */ - if (w->current_matrix == NULL) - goto set_x_cursor; - - /* Recognize when we are called to operate on rows that don't exist - anymore. This can happen when a window is split. */ - if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows) - goto set_x_cursor; - - set_output_cursor (&w->phys_cursor); - - /* Note that mouse_face_beg_row etc. are window relative. */ - for (i = dpyinfo->mouse_face_beg_row; - i <= dpyinfo->mouse_face_end_row; - i++) - { - int start_hpos, end_hpos, start_x; - struct glyph_row *row = MATRIX_ROW (w->current_matrix, i); + if (/* If window is in the process of being destroyed, don't bother + to do anything. */ + w->current_matrix != NULL + /* Don't update mouse highlight if hidden */ + && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden) + /* Recognize when we are called to operate on rows that don't exist + anymore. This can happen when a window is split. */ + && dpyinfo->mouse_face_end_row < w->current_matrix->nrows) + { + int phys_cursor_on_p = w->phys_cursor_on_p; + struct glyph_row *row, *first, *last; + + first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); + last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); + + for (row = first; row <= last && row->enabled_p; ++row) + { + int start_hpos, end_hpos, start_x; - /* Don't do anything if row doesn't have valid contents. */ - if (!row->enabled_p) - continue; + /* For all but the first row, the highlight starts at column 0. */ + if (row == first) + { + start_hpos = dpyinfo->mouse_face_beg_col; + start_x = dpyinfo->mouse_face_beg_x; + } + else + { + start_hpos = 0; + start_x = 0; + } - /* For all but the first row, the highlight starts at column 0. */ - if (i == dpyinfo->mouse_face_beg_row) - { - start_hpos = dpyinfo->mouse_face_beg_col; - start_x = dpyinfo->mouse_face_beg_x; - } - else - { - start_hpos = 0; - start_x = 0; - } + if (row == last) + end_hpos = dpyinfo->mouse_face_end_col; + else + end_hpos = row->used[TEXT_AREA]; - if (i == dpyinfo->mouse_face_end_row) - end_hpos = dpyinfo->mouse_face_end_col; - else - end_hpos = row->used[TEXT_AREA]; + if (end_hpos > start_hpos) + { + x_draw_glyphs (w, start_x, row, TEXT_AREA, + start_hpos, end_hpos, draw, 0); - /* If the cursor's in the text we are about to rewrite, turn the - cursor off. */ - if (!w->pseudo_window_p - && i == output_cursor.vpos - && output_cursor.hpos >= start_hpos - 1 - && output_cursor.hpos <= end_hpos) - { - x_update_window_cursor (w, 0); - cursor_off_p = 1; + row->mouse_face_p + = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; + } } - if (end_hpos > start_hpos) - { - x_draw_glyphs (w, start_x, row, TEXT_AREA, - start_hpos, end_hpos, draw, NULL, NULL, 0); - row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED; - } + /* When we've written over the cursor, arrange for it to + be displayed again. */ + if (phys_cursor_on_p && !w->phys_cursor_on_p) + x_display_cursor (w, 1, + w->phys_cursor.hpos, w->phys_cursor.vpos, + w->phys_cursor.x, w->phys_cursor.y); } - /* If we turned the cursor off, turn it back on. */ - if (cursor_off_p) - x_display_cursor (w, 1, - output_cursor.hpos, output_cursor.vpos, - output_cursor.x, output_cursor.y); - - output_cursor = saved_cursor; - - set_x_cursor: #if 0 /* TODO: mouse cursor */ /* Change the mouse cursor. */ if (draw == DRAW_NORMAL_TEXT) @@ -7421,7 +7539,6 @@ show_mouse_face (dpyinfo, draw) XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), f->output_data.x->nontext_cursor); #endif - ; } /* Clear out the mouse-highlighted active region. @@ -7488,6 +7605,8 @@ cancel_mouse_face (f) 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 *)); @@ -7503,7 +7622,7 @@ glyph_rect (f, x, y, rect) RECT *rect; { Lisp_Object window; - int part, found = 0; + int part; window = window_from_coordinates (f, x, y, &part, 0); if (!NILP (window)) @@ -7511,34 +7630,51 @@ glyph_rect (f, x, y, rect) 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; - int area; frame_to_window_pixel_xy (w, &x, &y); - - for (; !found && r < end && r->enabled_p; ++r) - if (r->y + r->height >= y) + + 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; - - for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g) - if (gx + g->pixel_width >= x) + + 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. */ + rect->left = XINT (w->left); + 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->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); rect->right = rect->left + g->pixel_width; - rect->bottom = rect->top + r->height; - found = 1; + return 1; } + + /* x is to the right of the last glyph in the row. */ + rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx); + rect->right = XINT (w->left) + XINT (w->width); + return 1; } } - return found; + /* 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) +static void +remember_mouse_glyph (f1, gx, gy) struct frame * f1; int gx, gy; { @@ -7805,7 +7941,7 @@ my_create_scrollbar (f, bar) (LPARAM) bar); } -//#define ATTACH_THREADS +/*#define ATTACH_THREADS*/ BOOL my_show_window (FRAME_PTR f, HWND hwnd, int how) @@ -7993,7 +8129,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) { HDC hdc; BLOCK_INPUT; - if (width && height) + if (width > 0 && height > 0) { hdc = get_frame_dc (f); w32_clear_area (f, hdc, left, top, width, height); @@ -8059,7 +8195,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE); my_show_window (f, hwnd, SW_NORMAL); - // InvalidateRect (w, NULL, FALSE); + /* InvalidateRect (w, NULL, FALSE); */ /* Remember new settings. */ XSETINT (bar->left, sb_left); @@ -8183,7 +8319,7 @@ w32_judge_scroll_bars (f) } /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind - is set to something other than no_event, it is enqueued. + is set to something other than NO_EVENT, it is enqueued. This may be called from a signal handler, so we have to ignore GC mark bits. */ @@ -8197,7 +8333,7 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event) if (! GC_WINDOWP (bar->window)) abort (); - emacs_event->kind = w32_scroll_bar_click; + emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT; emacs_event->code = 0; /* not really meaningful to distinguish up/down */ emacs_event->modifiers = msg->dwModifiers; @@ -8297,7 +8433,7 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event) } /* fall through */ default: - emacs_event->kind = no_event; + emacs_event->kind = NO_EVENT; return FALSE; } @@ -8411,12 +8547,6 @@ x_scroll_bar_clear (f) /* The main W32 event-reading loop - w32_read_socket. */ -/* Time stamp of enter window event. This is only used by w32_read_socket, - but we have to put it out here, since static variables within functions - sometimes don't work. */ - -static Time enter_timestamp; - /* Record the last 100 characters stored to help debug the loss-of-chars-during-GC problem. */ @@ -8472,7 +8602,7 @@ w32_read_socket (sd, bufp, numchars, expected) if (numchars <= 0) abort (); /* Don't think this happens. */ - /* TODO: tooltips, tool-bars, ghostscript integration, mouse + /* TODO: tool-bars, ghostscript integration, mouse cursors. */ while (get_next_msg (&msg, FALSE)) { @@ -8489,7 +8619,7 @@ w32_read_socket (sd, bufp, numchars, expected) /* We may get paint messages even though the client area is clipped - these are not expose events. */ DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f, - XSTRING (f->name)->data)); + SDATA (f->name))); } else if (f->async_visible != 1) { @@ -8498,13 +8628,13 @@ w32_read_socket (sd, bufp, numchars, expected) f->async_iconified = 0; SET_FRAME_GARBAGED (f); DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f, - XSTRING (f->name)->data)); + SDATA (f->name))); /* WM_PAINT serves as MapNotify as well, so report visibility changes properly. */ if (f->iconified) { - bufp->kind = deiconify_event; + bufp->kind = DEICONIFY_EVENT; XSETFRAME (bufp->frame_or_window, f); bufp->arg = Qnil; bufp++; @@ -8542,7 +8672,7 @@ w32_read_socket (sd, bufp, numchars, expected) if (numchars == 0) abort (); - bufp->kind = language_change_event; + bufp->kind = LANGUAGE_CHANGE_EVENT; XSETFRAME (bufp->frame_or_window, f); bufp->arg = Qnil; bufp->code = msg.msg.wParam; @@ -8559,10 +8689,16 @@ w32_read_socket (sd, bufp, numchars, expected) if (f && !f->iconified) { + if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) + { + dpyinfo->mouse_face_hidden = 1; + clear_mouse_face (dpyinfo); + } + if (temp_index == sizeof temp_buffer / sizeof (short)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; - bufp->kind = non_ascii_keystroke; + bufp->kind = NON_ASCII_KEYSTROKE_EVENT; bufp->code = msg.msg.wParam; bufp->modifiers = msg.dwModifiers; XSETFRAME (bufp->frame_or_window, f); @@ -8580,10 +8716,16 @@ w32_read_socket (sd, bufp, numchars, expected) if (f && !f->iconified) { + if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) + { + dpyinfo->mouse_face_hidden = 1; + clear_mouse_face (dpyinfo); + } + if (temp_index == sizeof temp_buffer / sizeof (short)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; - bufp->kind = ascii_keystroke; + bufp->kind = ASCII_KEYSTROKE_EVENT; bufp->code = msg.msg.wParam; bufp->modifiers = msg.dwModifiers; XSETFRAME (bufp->frame_or_window, f); @@ -8606,6 +8748,12 @@ w32_read_socket (sd, bufp, numchars, expected) else f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + if (dpyinfo->mouse_face_hidden) + { + dpyinfo->mouse_face_hidden = 0; + clear_mouse_face (dpyinfo); + } + if (f) note_mouse_movement (f, &msg.msg); else @@ -8641,6 +8789,8 @@ w32_read_socket (sd, bufp, numchars, expected) case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: { /* If we decide we want to generate an event to be seen by the rest of Emacs, we put it here. */ @@ -8649,7 +8799,7 @@ w32_read_socket (sd, bufp, numchars, expected) int button; int up; - emacs_event.kind = no_event; + emacs_event.kind = NO_EVENT; if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -8666,13 +8816,14 @@ w32_read_socket (sd, bufp, numchars, expected) && XFASTINT (XWINDOW (f->tool_bar_window)->height)) { Lisp_Object window; - int p; + int p, x, y; + + x = XFASTINT (emacs_event.x); + y = XFASTINT (emacs_event.y); /* Set x and y. */ - window = window_from_coordinates (f, - emacs_event.x, - emacs_event.y, - &p, 1); + window = window_from_coordinates (f, x, y, &p, 1); + if (EQ (window, f->tool_bar_window)) { w32_handle_tool_bar_click (f, &emacs_event); @@ -8692,8 +8843,9 @@ w32_read_socket (sd, bufp, numchars, expected) } } - parse_button (msg.msg.message, &button, &up); - + parse_button (msg.msg.message, HIWORD (msg.msg.wParam), + &button, &up); + if (up) { dpyinfo->grabbed &= ~ (1 << button); @@ -8736,16 +8888,6 @@ w32_read_socket (sd, bufp, numchars, expected) } break; - case WM_MENUSELECT: - { - HMENU menu = (HMENU) msg.msg.lParam; - UINT menu_item = (UINT) LOWORD (msg.msg.wParam); - UINT flags = (UINT) HIWORD (msg.msg.wParam); - - w32_menu_display_help (menu, menu_item, flags); - } - break; - case WM_DROPFILES: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); @@ -8776,8 +8918,22 @@ w32_read_socket (sd, bufp, numchars, expected) } case WM_WINDOWPOSCHANGED: + f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + if (f) + { + x_check_fullscreen_move(f); + if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT) + f->output_data.w32->want_fullscreen &= + ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH); + } + check_visibility = 1; + break; + case WM_ACTIVATE: case WM_ACTIVATEAPP: + f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + if (f) + x_check_fullscreen (f); check_visibility = 1; break; @@ -8797,6 +8953,15 @@ w32_read_socket (sd, bufp, numchars, expected) break; case WM_SHOWWINDOW: + /* wParam non-zero means Window is about to be shown, 0 means + about to be hidden. */ + /* Redo the mouse-highlight after the tooltip has gone. */ + if (!msg.msg.wParam && msg.msg.hwnd == tip_window) + { + tip_window = NULL; + redo_mouse_highlight (); + } + /* If window has been obscured or exposed by another window being maximised or minimised/restored, then recheck visibility of all frames. Direct changes to our own @@ -8826,7 +8991,7 @@ w32_read_socket (sd, bufp, numchars, expected) f->async_visible = 0; f->async_iconified = 1; - bufp->kind = iconify_event; + bufp->kind = ICONIFY_EVENT; XSETFRAME (bufp->frame_or_window, f); bufp->arg = Qnil; bufp++; @@ -8856,7 +9021,7 @@ w32_read_socket (sd, bufp, numchars, expected) f->output_data.w32->left_pos = x; f->output_data.w32->top_pos = y; - bufp->kind = deiconify_event; + bufp->kind = DEICONIFY_EVENT; XSETFRAME (bufp->frame_or_window, f); bufp->arg = Qnil; bufp++; @@ -8912,6 +9077,36 @@ w32_read_socket (sd, bufp, numchars, expected) check_visibility = 1; break; + case WM_MOUSELEAVE: + f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd); + if (f) + { + if (f == dpyinfo->mouse_face_mouse_frame) + { + /* If we move outside the frame, then we're + certainly no longer on any text in the frame. */ + clear_mouse_face (dpyinfo); + dpyinfo->mouse_face_mouse_frame = 0; + } + + /* Generate a nil HELP_EVENT to cancel a help-echo. + Do it only if there's something to cancel. + 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 = Qnil; + n = gen_help_event (bufp, numchars, + Qnil, frame, Qnil, Qnil, 0); + bufp += n, count += n, numchars -= n; + } + } + break; + case WM_SETFOCUS: f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd); @@ -8974,7 +9169,7 @@ w32_read_socket (sd, bufp, numchars, expected) if (numchars == 0) abort (); - bufp->kind = delete_window_event; + bufp->kind = DELETE_WINDOW_EVENT; XSETFRAME (bufp->frame_or_window, f); bufp->arg = Qnil; bufp++; @@ -8991,7 +9186,7 @@ w32_read_socket (sd, bufp, numchars, expected) if (numchars == 0) abort (); - bufp->kind = menu_bar_activate_event; + bufp->kind = MENU_BAR_ACTIVATE_EVENT; XSETFRAME (bufp->frame_or_window, f); bufp->arg = Qnil; bufp++; @@ -9076,6 +9271,11 @@ w32_read_socket (sd, bufp, numchars, expected) FOR_EACH_FRAME (tail, frame) { FRAME_PTR f = XFRAME (frame); + /* The tooltip has been drawn already. Avoid the + SET_FRAME_GARBAGED below. */ + if (EQ (frame, tip_frame)) + continue; + /* Check "visible" frames and mark each as obscured or not. Note that async_visible is nonzero for unobscured and obscured frames, but zero for hidden and iconified frames. */ @@ -9108,7 +9308,7 @@ w32_read_socket (sd, bufp, numchars, expected) if (!FRAME_OBSCURED_P (f)) { DebPrint (("frame %p (%s) obscured\n", f, - XSTRING (f->name)->data)); + SDATA (f->name))); } } else @@ -9120,7 +9320,7 @@ w32_read_socket (sd, bufp, numchars, expected) { SET_FRAME_GARBAGED (f); DebPrint (("obscured frame %p (%s) found to be visible\n", f, - XSTRING (f->name)->data)); + SDATA (f->name))); /* Force a redisplay sooner or later. */ record_asynch_buffer_change (); @@ -9141,21 +9341,24 @@ w32_read_socket (sd, bufp, numchars, expected) Text Cursor ***********************************************************************/ -/* Note if the text cursor of window W has been overwritten by a - drawing operation that outputs N glyphs starting at HPOS in the - line given by output_cursor.vpos. N < 0 means all the rest of the - line after HPOS has been written. */ +/* Notice if the text cursor of window W has been overwritten by a + drawing operation that outputs glyphs starting at START_X and + ending at END_X in the line given by output_cursor.vpos. + Coordinates are area-relative. END_X < 0 means all the rest + of the line after START_X has been written. */ static void -note_overwritten_text_cursor (w, hpos, n) +notice_overwritten_cursor (w, area, x0, x1, y0, y1) struct window *w; - int hpos, n; -{ - if (updated_area == TEXT_AREA - && output_cursor.vpos == w->phys_cursor.vpos - && hpos <= w->phys_cursor.hpos - && (n < 0 - || hpos + n > w->phys_cursor.hpos)) + enum glyph_row_area area; + int x0, x1, y0, y1; +{ + if (area == TEXT_AREA + && w->phys_cursor_on_p + && y0 <= w->phys_cursor.y + && y1 >= w->phys_cursor.y + w->phys_cursor_height + && x0 <= w->phys_cursor.x + && (x1 < 0 || x1 > w->phys_cursor.x)) w->phys_cursor_on_p = 0; } @@ -9192,8 +9395,8 @@ w32_clip_to_row (w, row, hdc, whole_line_p) the rectangle to the left and increase its width. */ if (whole_line_p) { - clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f); - clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f); + clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f); + clip_rect.right += FRAME_X_FRINGE_WIDTH (f); } w32_set_clip_rectangle (hdc, &clip_rect); @@ -9219,7 +9422,7 @@ x_draw_hollow_cursor (w, row) 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 - 1; + 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. */ @@ -9231,7 +9434,7 @@ x_draw_hollow_cursor (w, row) 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 - 1; + wd = cursor_glyph->pixel_width; if (cursor_glyph->type == STRETCH_GLYPH && !x_stretch_cursor_p) wd = min (CANON_X_UNIT (f), wd); @@ -9253,10 +9456,11 @@ x_draw_hollow_cursor (w, row) --gerd. */ static void -x_draw_bar_cursor (w, row, width) +x_draw_bar_cursor (w, row, width, kind) struct window *w; struct glyph_row *row; int width; + enum text_cursor_kinds kind; { struct frame *f = XFRAME (w->frame); struct glyph *cursor_glyph; @@ -9281,17 +9485,38 @@ x_draw_bar_cursor (w, row, width) } else { + COLORREF cursor_color = f->output_data.w32->cursor_pixel; + struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); + if (width < 0) width = f->output_data.w32->cursor_width; + width = min (cursor_glyph->pixel_width, width); + + /* If the glyph's background equals the color we normally draw + the bar cursor in, the bar cursor in its normal color is + invisible. Use the glyph's foreground color instead in this + case, on the assumption that the glyph's colors are chosen so + that the glyph is legible. */ + if (face->background == cursor_color) + cursor_color = face->foreground; x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); hdc = get_frame_dc (f); w32_clip_to_row (w, row, hdc, 0); - w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel, - x, - WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), - min (cursor_glyph->pixel_width, width), - row->height); + + if (kind == BAR_CURSOR) + { + w32_fill_area (f, hdc, cursor_color, x, + WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), + width, row->height); + } + else + { + w32_fill_area (f, hdc, cursor_color, x, + WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + + row->height - width), + cursor_glyph->pixel_width, width); + } release_frame_dc (f, hdc); } } @@ -9324,9 +9549,11 @@ x_draw_phys_cursor_glyph (w, row, hl) glyphs and mini-buffer. */ if (w->phys_cursor.hpos < row->used[TEXT_AREA]) { + int on_p = w->phys_cursor_on_p; x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, w->phys_cursor.hpos, w->phys_cursor.hpos + 1, - hl, 0, 0, 0); + hl, 0); + w->phys_cursor_on_p = on_p; /* When we erase the cursor, and ROW is overlapped by other rows, make sure that these overlapping parts of other rows @@ -9377,6 +9604,12 @@ x_erase_phys_cursor (w) if (!cursor_row->enabled_p) goto mark_cursor_off; + /* If row is completely invisible, don't attempt to delete a cursor which + isn't there. This may happen if cursor is at top of window, and + we switch to a buffer with a header line in that window. */ + if (cursor_row->visible_height <= 0) + goto mark_cursor_off; + /* This can happen when the new row is shorter than the old one. In this case, either x_draw_glyphs or clear_end_of_line should have cleared the cursor. Note that we wouldn't be @@ -9426,8 +9659,6 @@ x_erase_phys_cursor (w) /* Erase the cursor by redrawing the character underneath it. */ if (mouse_face_here_p) hl = DRAW_MOUSE_FACE; - else if (cursor_row->inverse_p) - hl = DRAW_INVERSE_VIDEO; else hl = DRAW_NORMAL_TEXT; x_draw_phys_cursor_glyph (w, cursor_row, hl); @@ -9483,6 +9714,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) struct glyph_matrix *current_glyphs; struct glyph_row *glyph_row; struct glyph *glyph; + int cursor_non_selected; + int active_cursor = 1; /* This is pointless on invisible frames, and dangerous on garbaged windows and frames; in the latter case, the frame or window may @@ -9518,6 +9751,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) the cursor type given by the frame parameter. If explicitly marked off, draw no cursor. In all other cases, we want a hollow box cursor. */ + cursor_non_selected + = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows, + w->buffer)); new_cursor_width = -1; if (cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f) @@ -9526,24 +9762,28 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) if (w == XWINDOW (echo_area_window)) new_cursor_type = FRAME_DESIRED_CURSOR (f); else - new_cursor_type = HOLLOW_BOX_CURSOR; + { + if (cursor_non_selected) + new_cursor_type = HOLLOW_BOX_CURSOR; + else + new_cursor_type = NO_CURSOR; + active_cursor = 0; + } } else { if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame || w != XWINDOW (f->selected_window)) { - extern int cursor_in_non_selected_windows; + active_cursor = 0; if (MINI_WINDOW_P (w) - || !cursor_in_non_selected_windows + || !cursor_non_selected || NILP (XBUFFER (w->buffer)->cursor_type)) new_cursor_type = NO_CURSOR; else new_cursor_type = HOLLOW_BOX_CURSOR; } - else if (w->cursor_off_p) - new_cursor_type = NO_CURSOR; else { struct buffer *b = XBUFFER (w->buffer); @@ -9553,6 +9793,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) else new_cursor_type = x_specified_cursor_type (b->cursor_type, &new_cursor_width); + if (w->cursor_off_p) + { + if (new_cursor_type == FILLED_BOX_CURSOR) + new_cursor_type = HOLLOW_BOX_CURSOR; + else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1) + new_cursor_width = 1; + else + new_cursor_type = NO_CURSOR; + } } } @@ -9563,7 +9812,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) && (!on || w->phys_cursor.x != x || w->phys_cursor.y != y - || new_cursor_type != w->phys_cursor_type)) + || new_cursor_type != w->phys_cursor_type + || (new_cursor_type == BAR_CURSOR + && new_cursor_width != w->phys_cursor_width))) x_erase_phys_cursor (w); /* If the cursor is now invisible and we want it to be visible, @@ -9579,9 +9830,50 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) w->phys_cursor.y = glyph_row->y; w->phys_cursor.hpos = hpos; w->phys_cursor.vpos = vpos; - w->phys_cursor_type = new_cursor_type; + + /* If the user wants to use the system caret, make sure our own + cursor remains invisible. */ + if (w32_use_visible_system_caret) + { + if (w->phys_cursor_type != NO_CURSOR) + x_erase_phys_cursor (w); + + new_cursor_type = w->phys_cursor_type = NO_CURSOR; + w->phys_cursor_width = -1; + } + else + { + w->phys_cursor_type = new_cursor_type; + w->phys_cursor_width = new_cursor_width; + } + w->phys_cursor_on_p = 1; + /* If this is the active cursor, we need to track it with the + system caret, so third party software like screen magnifiers + and speech synthesizers can follow the cursor. */ + if (active_cursor) + { + HWND hwnd = FRAME_W32_WINDOW (f); + + w32_system_caret_x + = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + w32_system_caret_y + = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y) + + glyph_row->ascent - w->phys_cursor_ascent); + + /* If the size of the active cursor changed, destroy the old + system caret. */ + if (w32_system_caret_hwnd + && (w32_system_caret_height != w->phys_cursor_height)) + PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0); + + w32_system_caret_height = w->phys_cursor_height; + + /* Move the system caret. */ + PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0); + } + switch (new_cursor_type) { case HOLLOW_BOX_CURSOR: @@ -9593,7 +9885,11 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) break; case BAR_CURSOR: - x_draw_bar_cursor (w, glyph_row, new_cursor_width); + x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR); + break; + + case HBAR_CURSOR: + x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR); break; case NO_CURSOR: @@ -9695,7 +9991,7 @@ x_bitmap_icon (f, icon) if (NILP (icon)) hicon = LoadIcon (hinst, EMACS_CLASS); else if (STRINGP (icon)) - hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0, + hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); else if (SYMBOLP (icon)) { @@ -9825,7 +10121,7 @@ x_new_fontset (f, fontsetname) to do. */ return fontset_name (fontset); - result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data)); + result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); if (!STRINGP (result)) /* Can't load ASCII font. */ @@ -9837,6 +10133,90 @@ x_new_fontset (f, fontsetname) return build_string (fontsetname); } +/* Compute actual fringe widths */ + +void +x_compute_fringe_widths (f, redraw) + struct frame *f; + int redraw; +{ + int o_left = f->output_data.w32->left_fringe_width; + int o_right = f->output_data.w32->right_fringe_width; + int o_cols = f->output_data.w32->fringe_cols; + + Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist); + Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist); + int left_fringe_width, right_fringe_width; + + if (!NILP (left_fringe)) + left_fringe = Fcdr (left_fringe); + if (!NILP (right_fringe)) + right_fringe = Fcdr (right_fringe); + + left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 : + XINT (left_fringe)); + right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 : + XINT (right_fringe)); + + if (left_fringe_width || right_fringe_width) + { + int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width; + int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width; + int conf_wid = left_wid + right_wid; + int font_wid = FONT_WIDTH (f->output_data.w32->font); + int cols = (left_wid + right_wid + font_wid-1) / font_wid; + int real_wid = cols * font_wid; + if (left_wid && right_wid) + { + if (left_fringe_width < 0) + { + /* Left fringe width is fixed, adjust right fringe if necessary */ + f->output_data.w32->left_fringe_width = left_wid; + f->output_data.w32->right_fringe_width = real_wid - left_wid; + } + else if (right_fringe_width < 0) + { + /* Right fringe width is fixed, adjust left fringe if necessary */ + f->output_data.w32->left_fringe_width = real_wid - right_wid; + f->output_data.w32->right_fringe_width = right_wid; + } + else + { + /* Adjust both fringes with an equal amount. + Note that we are doing integer arithmetic here, so don't + lose a pixel if the total width is an odd number. */ + int fill = real_wid - conf_wid; + f->output_data.w32->left_fringe_width = left_wid + fill/2; + f->output_data.w32->right_fringe_width = right_wid + fill - fill/2; + } + } + else if (left_fringe_width) + { + f->output_data.w32->left_fringe_width = real_wid; + f->output_data.w32->right_fringe_width = 0; + } + else + { + f->output_data.w32->left_fringe_width = 0; + f->output_data.w32->right_fringe_width = real_wid; + } + f->output_data.w32->fringe_cols = cols; + f->output_data.w32->fringes_extra = real_wid; + } + else + { + f->output_data.w32->left_fringe_width = 0; + f->output_data.w32->right_fringe_width = 0; + f->output_data.w32->fringe_cols = 0; + f->output_data.w32->fringes_extra = 0; + } + + if (redraw && FRAME_VISIBLE_P (f)) + if (o_left != f->output_data.w32->left_fringe_width || + o_right != f->output_data.w32->right_fringe_width || + o_cols != f->output_data.w32->fringe_cols) + redraw_frame (f); +} /*********************************************************************** TODO: W32 Input Methods @@ -9950,6 +10330,115 @@ x_set_offset (f, xoff, yoff, change_gravity) UNBLOCK_INPUT; } + +/* Check if we need to resize the frame due to a fullscreen request. + If so needed, resize the frame. */ +static void +x_check_fullscreen (f) + struct frame *f; +{ + if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH) + { + int width, height, ign; + + x_real_positions (f, &f->output_data.w32->left_pos, + &f->output_data.w32->top_pos); + + 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. */ + if (f->width != width || f->height != height) + { + change_frame_size (f, height, width, 0, 1, 0); + SET_FRAME_GARBAGED (f); + cancel_mouse_face (f); + + /* Wait for the change of frame size to occur */ + f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT; + } + } +} + +/* 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->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT) + { + int expect_top = f->output_data.w32->top_pos; + int expect_left = f->output_data.w32->left_pos; + + if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT) + expect_top = 0; + if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH) + expect_left = 0; + + if (expect_top != f->output_data.w32->top_pos + || expect_left != f->output_data.w32->left_pos) + x_set_offset (f, expect_left, expect_top, 1); + + /* Just do this once */ + f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT; + } +} + + +/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the + wanted positions of the WM window (not emacs window). + Return in *WIDTH and *HEIGHT the wanted width and height of Emacs + window (FRAME_X_WINDOW). + */ +void +x_fullscreen_adjust (f, width, height, top_pos, left_pos) + struct frame *f; + int *width; + int *height; + int *top_pos; + int *left_pos; +{ + int newwidth = f->width, newheight = f->height; + + *top_pos = f->output_data.w32->top_pos; + *left_pos = f->output_data.w32->left_pos; + + if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT) + { + int ph; + + ph = FRAME_X_DISPLAY_INFO (f)->height; + newheight = PIXEL_TO_CHAR_HEIGHT (f, ph); + ph = CHAR_TO_PIXEL_HEIGHT (f, newheight) + - f->output_data.w32->y_pixels_diff; + newheight = PIXEL_TO_CHAR_HEIGHT (f, ph); + *top_pos = 0; + } + + if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH) + { + int pw; + + pw = FRAME_X_DISPLAY_INFO (f)->width; + newwidth = PIXEL_TO_CHAR_WIDTH (f, pw); + pw = CHAR_TO_PIXEL_WIDTH (f, newwidth) + - f->output_data.w32->x_pixels_diff; + newwidth = PIXEL_TO_CHAR_WIDTH (f, pw); + *left_pos = 0; + } + + *width = newwidth; + *height = newheight; +} + + /* 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. @@ -9970,8 +10459,9 @@ x_set_window_size (f, change_gravity, cols, rows) = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) ? 0 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font))); - f->output_data.w32->flags_areas_extra - = FRAME_FLAGS_AREA_WIDTH (f); + + x_compute_fringe_widths (f, 0); + pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); @@ -10221,7 +10711,7 @@ x_make_frame_visible (f) f->output_data.w32->asked_for_visible = 1; -// my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); +/* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */ my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL); } @@ -10557,11 +11047,11 @@ w32_initialize_display_info (display_name) dpyinfo->name_list_element = XCAR (w32_display_name_list); dpyinfo->w32_id_name - = (char *) xmalloc (XSTRING (Vinvocation_name)->size - + XSTRING (Vsystem_name)->size + = (char *) xmalloc (SCHARS (Vinvocation_name) + + SCHARS (Vsystem_name) + 2); sprintf (dpyinfo->w32_id_name, "%s@%s", - XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data); + SDATA (Vinvocation_name), SDATA (Vsystem_name)); /* Default Console mode values - overridden when running in GUI mode with values obtained from system metrics. */ @@ -10580,6 +11070,7 @@ w32_initialize_display_info (display_name) dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID; dpyinfo->mouse_face_window = Qnil; dpyinfo->mouse_face_overlay = Qnil; + dpyinfo->mouse_face_hidden = 0; /* TODO: dpyinfo->gray */ } @@ -10787,6 +11278,11 @@ w32_initialize () off the bottom */ baud_rate = 19200; + w32_system_caret_hwnd = NULL; + w32_system_caret_height = 0; + w32_system_caret_x = 0; + w32_system_caret_y = 0; + last_tool_bar_item = -1; any_help_event_p = 0; @@ -10868,43 +11364,43 @@ syms_of_w32term () DEFVAR_INT ("w32-num-mouse-buttons", &Vw32_num_mouse_buttons, - "Number of physical mouse buttons."); + doc: /* Number of physical mouse buttons. */); Vw32_num_mouse_buttons = Qnil; DEFVAR_LISP ("w32-swap-mouse-buttons", &Vw32_swap_mouse_buttons, - "Swap the mapping of middle and right mouse buttons.\n\ -When nil, middle button is mouse-2 and right button is mouse-3."); + doc: /* Swap the mapping of middle and right mouse buttons. +When nil, middle button is mouse-2 and right button is mouse-3. */); Vw32_swap_mouse_buttons = Qnil; DEFVAR_LISP ("w32-grab-focus-on-raise", &Vw32_grab_focus_on_raise, - "Raised frame grabs input focus.\n\ -When t, `raise-frame' grabs input focus as well. This fits well\n\ -with the normal Windows click-to-focus policy, but might not be\n\ -desirable when using a point-to-focus policy."); + doc: /* Raised frame grabs input focus. +When t, `raise-frame' grabs input focus as well. This fits well +with the normal Windows click-to-focus policy, but might not be +desirable when using a point-to-focus policy. */); Vw32_grab_focus_on_raise = Qt; DEFVAR_LISP ("w32-capslock-is-shiftlock", &Vw32_capslock_is_shiftlock, - "Apply CapsLock state to non character input keys.\n\ -When nil, CapsLock only affects normal character input keys."); + doc: /* Apply CapsLock state to non character input keys. +When nil, CapsLock only affects normal character input keys. */); Vw32_capslock_is_shiftlock = Qnil; DEFVAR_LISP ("w32-recognize-altgr", &Vw32_recognize_altgr, - "Recognize right-alt and left-ctrl as AltGr.\n\ -When nil, the right-alt and left-ctrl key combination is\n\ -interpreted normally."); + doc: /* Recognize right-alt and left-ctrl as AltGr. +When nil, the right-alt and left-ctrl key combination is +interpreted normally. */); Vw32_recognize_altgr = Qt; DEFVAR_BOOL ("w32-enable-unicode-output", &w32_enable_unicode_output, - "Enable the use of Unicode for text output if non-nil.\n\ -Unicode output may prevent some third party applications for displaying\n\ -Far-East Languages on Windows 95/98 from working properly.\n\ -NT uses Unicode internally anyway, so this flag will probably have no\n\ -affect on NT machines."); + doc: /* Enable the use of Unicode for text output if non-nil. +Unicode output may prevent some third party applications for displaying +Far-East Languages on Windows 95/98 from working properly. +NT uses Unicode internally anyway, so this flag will probably have no +affect on NT machines. */); w32_enable_unicode_output = 1; help_echo = Qnil; @@ -10917,24 +11413,45 @@ affect on NT machines."); staticpro (&previous_help_echo); help_echo_pos = -1; + DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window, + doc: /* *Non-nil means autoselect window with mouse pointer. */); + mouse_autoselect_window = 0; + + DEFVAR_BOOL ("w32-use-visible-system-caret", + &w32_use_visible_system_caret, + doc: /* Flag to make the system caret visible. +When this is non-nil, Emacs will indicate the position of point by +using the system caret instead of drawing its own cursor. Some screen +reader software does not track the system cursor properly when it is +invisible, and gets confused by Emacs drawing its own cursor, so this +variable is initialized to t when Emacs detects that screen reader +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; + DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p, - "*Non-nil means draw block cursor as wide as the glyph under it.\n\ -For example, if a block cursor is over a tab, it will be drawn as\n\ -wide as that tab on the display."); + doc: /* *Non-nil means draw block cursor as wide as the glyph under it. +For example, if a block cursor is over a tab, it will be drawn as +wide as that tab on the display. */); x_stretch_cursor_p = 0; -#if 0 /* TODO: Setting underline position from font properties. */ DEFVAR_BOOL ("x-use-underline-position-properties", &x_use_underline_position_properties, - "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\ -Nil means ignore them. If you encounter fonts with bogus\n\ -UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\ -to 4.1, set this to nil."); + 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. */); x_use_underline_position_properties = 1; -#endif DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, - "If not nil, Emacs uses toolkit scroll bars."); + doc: /* If not nil, Emacs uses toolkit scroll bars. */); Vx_toolkit_scroll_bars = Qt; staticpro (&last_mouse_motion_frame);