#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
\f
-/* 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,
`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: `<-'. */
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. */
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,
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. */
/* 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. */
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 *));
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;
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);
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;
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;
}
/* 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. */
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;
/* 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);
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);
}
-/* 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);
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);
}
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);
}
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.
/* 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;
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
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 *,
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);
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);
}
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;
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;
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);
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);
}
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);
}
}
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
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
|| 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
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;
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;
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);
}
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);
}
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
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;
}
}
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);
&& 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
{
struct glyph *start;
int len;
{
- int x, hpos, real_start, real_end;
+ int x, hpos;
xassert (updated_window && updated_row);
BLOCK_INPUT;
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;
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);
/* 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;
/* 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)
{
{
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);
height = bottom_y - from_y;
else
height = run->height;
+ expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
}
else
{
height = bottom_y - to_y;
else
height = run->height;
+ expect_dirty = CreateRectRgn (x, y, x + width, to_y);
}
BLOCK_INPUT;
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);
}
/* 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
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);
}
}
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])
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;
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;
{
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);
}
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
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;
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;
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);
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;
}
}
-/* This is used for debugging, to turn off note_mouse_highlight. */
-
-int disable_mouse_highlight;
-
-
\f
/************************************************************************
Mouse Face
/* 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
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)
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
if (popup_activated ())
return;
- if (disable_mouse_highlight
+ if (NILP (Vmouse_highlight)
|| !f->glyphs_initialized_p)
return;
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);
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,
{
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
/* 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);
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);
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;
}
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))
#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.
{
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)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->nontext_cursor);
#endif
- ;
}
/* Clear out the mouse-highlighted active region.
\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 *));
RECT *rect;
{
Lisp_Object window;
- int part, found = 0;
+ int part;
window = window_from_coordinates (f, x, y, &part, 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;
- 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;
{
(LPARAM) bar);
}
-//#define ATTACH_THREADS
+/*#define ATTACH_THREADS*/
BOOL
my_show_window (FRAME_PTR f, HWND hwnd, int how)
{
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);
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);
}
/* 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. */
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;
}
/* fall through */
default:
- emacs_event->kind = no_event;
+ emacs_event->kind = NO_EVENT;
return FALSE;
}
\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. */
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))
{
/* 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)
{
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++;
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;
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);
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);
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
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. */
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))
&& 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);
}
}
- parse_button (msg.msg.message, &button, &up);
-
+ parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
+ &button, &up);
+
if (up)
{
dpyinfo->grabbed &= ~ (1 << button);
}
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);
}
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;
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
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++;
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++;
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);
if (numchars == 0)
abort ();
- bufp->kind = delete_window_event;
+ bufp->kind = DELETE_WINDOW_EVENT;
XSETFRAME (bufp->frame_or_window, f);
bufp->arg = Qnil;
bufp++;
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++;
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. */
if (!FRAME_OBSCURED_P (f))
{
DebPrint (("frame %p (%s) obscured\n", f,
- XSTRING (f->name)->data));
+ SDATA (f->name)));
}
}
else
{
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 ();
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;
}
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);
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. */
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);
--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;
}
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);
}
}
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
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
/* 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);
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
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)
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);
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;
+ }
}
}
&& (!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,
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:
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:
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))
{
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. */
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);
+}
\f
/***********************************************************************
TODO: W32 Input Methods
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.
= (!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);
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);
}
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. */
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 */
}
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;
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;
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);