/* Implementation of GUI terminal on the Microsoft W32 API.
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
DWORD dwMainThreadId = 0;
HANDLE hMainThread = NULL;
-#ifndef SIF_ALL
-/* These definitions are new with Windows 95. */
-#define SIF_RANGE 0x0001
-#define SIF_PAGE 0x0002
-#define SIF_POS 0x0004
-#define SIF_DISABLENOSCROLL 0x0008
-#define SIF_TRACKPOS 0x0010
-#define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
-
-typedef struct tagSCROLLINFO
-{
- UINT cbSize;
- UINT fMask;
- int nMin;
- int nMax;
- UINT nPage;
- int nPos;
- int nTrackPos;
-} SCROLLINFO, FAR *LPSCROLLINFO;
-typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
-#endif /* SIF_ALL */
-
-/* Dynamic linking to new proportional scroll bar functions. */
-int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
-BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
-
int vertical_scroll_bar_min_handle;
int vertical_scroll_bar_top_border;
int vertical_scroll_bar_bottom_border;
/* Where the mouse was last time we reported a mouse event. */
static RECT last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
static Lisp_Object last_mouse_press_frame;
int w32_num_mouse_buttons;
else
x = s->x;
- if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
+ if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
SetBkMode (s->hdc, TRANSPARENT);
else
SetBkMode (s->hdc, OPAQUE);
{
/* If `x-stretch-block-cursor' is nil, don't draw a block cursor
as wide as the stretch glyph. */
- int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
+ int width, background_width = s->background_width;
+ int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+ if (x < left_x)
+ {
+ background_width -= left_x - x;
+ x = left_x;
+ }
+ width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
/* Draw cursor. */
- x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+ x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
/* Clear rest using the GC of the original non-cursor face. */
- if (width < s->background_width)
+ if (width < background_width)
{
XGCValues *gc = s->face->gc;
- int x = s->x + width, y = s->y;
- int w = s->background_width - width, h = s->height;
+ int y = s->y;
+ int w = background_width - width, h = s->height;
RECT r;
HDC hdc = s->hdc;
+ x += width;
if (s->row->mouse_face_p
&& cursor_in_mouse_face_p (s->w))
{
}
}
else if (!s->background_filled_p)
- x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
- s->height);
+ {
+ int background_width = s->background_width;
+ int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+ if (x < left_x)
+ {
+ background_width -= left_x - x;
+ x = left_x;
+ }
+ if (background_width > 0)
+ x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+ }
s->background_filled_p = 1;
}
/* If S draws into the background of its successor, draw the
background of the successor first so that S can draw into it.
This makes S->next use XDrawString instead of XDrawImageString. */
- if (s->next && s->right_overhang && !s->for_overlaps_p)
+ if (s->next && s->right_overhang && !s->for_overlaps)
{
xassert (s->next->img == NULL);
x_set_glyph_string_gc (s->next);
/* Draw relief (if any) in advance for char/composition so that the
glyph string can be drawn over it. */
- if (!s->for_overlaps_p
+ if (!s->for_overlaps
&& s->face->box != FACE_NO_BOX
&& (s->first_glyph->type == CHAR_GLYPH
|| s->first_glyph->type == COMPOSITE_GLYPH))
break;
case CHAR_GLYPH:
- if (s->for_overlaps_p)
+ if (s->for_overlaps)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 0);
break;
case COMPOSITE_GLYPH:
- if (s->for_overlaps_p || s->gidx > 0)
+ if (s->for_overlaps || s->gidx > 0)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 1);
abort ();
}
- if (!s->for_overlaps_p)
+ if (!s->for_overlaps)
{
/* Draw underline. */
if (s->face->underline_p
result->modifiers = (msg->dwModifiers
| ((delta < 0 ) ? down_modifier : up_modifier));
- p.x = LOWORD (msg->msg.lParam);
- p.y = HIWORD (msg->msg.lParam);
+ /* With multiple monitors, we can legitimately get negative
+ coordinates, so cast to short to interpret them correctly. */
+ p.x = (short) LOWORD (msg->msg.lParam);
+ p.y = (short) HIWORD (msg->msg.lParam);
ScreenToClient (msg->msg.hwnd, &p);
XSETINT (result->x, p.x);
XSETINT (result->y, p.y);
DragFinish (hdrop);
XSETFRAME (frame, f);
- result->frame_or_window = Fcons (frame, files);
- result->arg = Qnil;
+ result->frame_or_window = frame;
+ result->arg = files;
return Qnil;
}
static MSG last_mouse_motion_event;
static Lisp_Object last_mouse_motion_frame;
-static void remember_mouse_glyph P_ ((struct frame *, int, int));
-
-static void
+static int
note_mouse_movement (frame, msg)
FRAME_PTR frame;
MSG *msg;
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
+ last_mouse_glyph_frame = 0;
+ return 1;
}
/* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (mouse_x < last_mouse_glyph.left
- || mouse_x > last_mouse_glyph.right
- || mouse_y < last_mouse_glyph.top
- || mouse_y > last_mouse_glyph.bottom)
+ if (frame != last_mouse_glyph_frame
+ || mouse_x < last_mouse_glyph.left
+ || mouse_x >= last_mouse_glyph.right
+ || mouse_y < last_mouse_glyph.top
+ || mouse_y >= last_mouse_glyph.bottom)
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
gets called when mouse tracking is enabled but we also need
to keep track of the mouse for help_echo and highlighting at
other times. */
- remember_mouse_glyph (frame, mouse_x, mouse_y);
+ remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
+ last_mouse_glyph_frame = frame;
+ return 1;
}
+
+ return 0;
}
\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 int glyph_rect P_ ((struct frame *f, int, int, RECT *));
-
static void
redo_mouse_highlight ()
{
PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
}
-
-/* Try to determine frame pixel position and size of the glyph under
- frame pixel coordinates X/Y on frame F . Return the position and
- size in *RECT. Value is non-zero if we could compute these
- values. */
-
-static int
-glyph_rect (f, x, y, rect)
- struct frame *f;
- int x, y;
- RECT *rect;
-{
- Lisp_Object window;
-
- window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-
- if (!NILP (window))
- {
- struct window *w = XWINDOW (window);
- struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- struct glyph_row *end = r + w->current_matrix->nrows - 1;
-
- for (; r < end && r->enabled_p; ++r)
- if (r->y <= y && r->y + r->height > y)
- {
- /* Found the row at y. */
- struct glyph *g = r->glyphs[TEXT_AREA];
- struct glyph *end = g + r->used[TEXT_AREA];
- int gx;
-
- rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
- rect->bottom = rect->top + r->height;
-
- if (x < r->x)
- {
- /* x is to the left of the first glyph in the row. */
- /* Shouldn't this be a pixel value?
- WINDOW_LEFT_EDGE_X (w) seems to be the right value.
- ++KFS */
- rect->left = WINDOW_LEFT_EDGE_COL (w);
- rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
- return 1;
- }
-
- for (gx = r->x; g < end; gx += g->pixel_width, ++g)
- if (gx <= x && gx + g->pixel_width > x)
- {
- /* x is on a glyph. */
- rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- rect->right = rect->left + g->pixel_width;
- return 1;
- }
-
- /* x is to the right of the last glyph in the row. */
- rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- /* Shouldn't this be a pixel value?
- WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
- ++KFS */
- rect->right = WINDOW_RIGHT_EDGE_COL (w);
- return 1;
- }
- }
-
- /* The y is not on any row. */
- return 0;
-}
-
-/* Record the position of the mouse in last_mouse_glyph. */
-static void
-remember_mouse_glyph (f1, gx, gy)
- struct frame * f1;
- int gx, gy;
-{
- if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
- {
- int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
- int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-
- /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
- round down even for negative values. */
- if (gx < 0)
- gx -= width - 1;
- if (gy < 0)
- gy -= height - 1;
-#if 0
- /* This was the original code from XTmouse_position, but it seems
- to give the position of the glyph diagonally next to the one
- the mouse is over. */
- gx = (gx + width - 1) / width * width;
- gy = (gy + height - 1) / height * height;
-#else
- gx = gx / width * width;
- gy = gy / height * height;
-#endif
-
- last_mouse_glyph.left = gx;
- last_mouse_glyph.top = gy;
- last_mouse_glyph.right = gx + width;
- last_mouse_glyph.bottom = gy + height;
- }
-}
-
/* Return the current position of the mouse.
*fp should be a frame which indicates which display to ask about.
on it, i.e. into the same rectangles that matrices on
the frame are divided into. */
-#if OLD_REDISPLAY_CODE
- int ignore1, ignore2;
-
- ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
-
- pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
- &last_mouse_glyph,
- FRAME_W32_DISPLAY_INFO (f1)->grabbed
- || insist);
-#else
ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
- remember_mouse_glyph (f1, pt.x, pt.y);
-#endif
+ remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
+ last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
int sb_page, sb_pos;
BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
+ SCROLLINFO si;
if (whole)
{
BLOCK_INPUT;
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
-
- si.cbSize = sizeof (si);
- /* Only update page size if currently dragging, to reduce
- flicker effects. */
- if (draggingp)
- si.fMask = SIF_PAGE;
- else
- si.fMask = SIF_PAGE | SIF_POS;
- si.nPage = sb_page;
- si.nPos = sb_pos;
-
- pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
- }
+ si.cbSize = sizeof (si);
+ /* Only update page size if currently dragging, to reduce
+ flicker effects. */
+ if (draggingp)
+ si.fMask = SIF_PAGE;
else
- SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
+ si.fMask = SIF_PAGE | SIF_POS;
+ si.nPage = sb_page;
+ si.nPos = sb_pos;
+
+ SetScrollInfo (w, SB_CTL, &si, !draggingp);
UNBLOCK_INPUT;
}
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HWND hwnd;
+ SCROLLINFO si;
struct scroll_bar *bar
= XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
hwnd = my_create_scrollbar (f, bar);
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
-
- si.cbSize = sizeof (si);
- si.fMask = SIF_ALL;
- si.nMin = 0;
- si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
- + VERTICAL_SCROLL_BAR_MIN_HANDLE;
- si.nPage = si.nMax;
- si.nPos = 0;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+ + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+ si.nPage = si.nMax;
+ si.nPos = 0;
- pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
- }
- else
- {
- SetScrollRange (hwnd, SB_CTL, 0,
- VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
- SetScrollPos (hwnd, SB_CTL, 0, FALSE);
- }
+ SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
else
{
HDC hdc;
+ SCROLLINFO si;
+
BLOCK_INPUT;
if (width && height)
{
MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
max (height, 1), TRUE);
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
- si.cbSize = sizeof (si);
- si.fMask = SIF_RANGE;
- si.nMin = 0;
- si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
- + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+ + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+
+ SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
- pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
- }
- else
- SetScrollRange (hwnd, SB_CTL, 0,
- VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
my_show_window (f, hwnd, SW_NORMAL);
/* InvalidateRect (w, NULL, FALSE); */
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
int y;
int dragging = !NILP (bar->dragging);
+ SCROLLINFO si;
- if (pfnGetScrollInfo)
- {
- SCROLLINFO si;
-
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
- pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
- y = si.nPos;
- }
- else
- y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
+ GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
+ y = si.nPos;
bar->dragging = Qnil;
emacs_event->part = scroll_bar_handle;
/* "Silently" update current position. */
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
+ {
+ SCROLLINFO si;
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
- si.nPos = y;
- /* Remember apparent position (we actually lag behind the real
- position, so don't set that directly. */
- last_scroll_bar_drag_pos = y;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ si.nPos = y;
+ /* Remember apparent position (we actually lag behind the real
+ position, so don't set that directly. */
+ last_scroll_bar_drag_pos = y;
- pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
- }
- else
- SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
+ }
break;
case SB_ENDSCROLL:
/* If this is the end of a drag sequence, then reset the scroll
nothing. */
if (dragging)
{
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
- int start = XINT (bar->start);
- int end = XINT (bar->end);
-
- si.cbSize = sizeof (si);
- si.fMask = SIF_PAGE | SIF_POS;
- si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
- si.nPos = last_scroll_bar_drag_pos;
- pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
- }
- else
- SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
+ SCROLLINFO si;
+ int start = XINT (bar->start);
+ int end = XINT (bar->end);
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_POS;
+ si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+ si.nPos = last_scroll_bar_drag_pos;
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
}
/* fall through */
default:
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int pos;
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ SCROLLINFO si;
BLOCK_INPUT;
*fp = f;
*bar_window = bar->window;
- if (pfnGetScrollInfo)
- {
- SCROLLINFO si;
-
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
- pfnGetScrollInfo (w, SB_CTL, &si);
- pos = si.nPos;
- top_range = si.nMax - si.nPage + 1;
- }
- else
- pos = GetScrollPos (w, SB_CTL);
+ GetScrollInfo (w, SB_CTL, &si);
+ pos = si.nPos;
+ top_range = si.nMax - si.nPage + 1;
switch (LOWORD (last_mouse_scroll_bar_pos))
{
if (f && !f->iconified)
{
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+ && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_hidden = 1;
if (f && !f->iconified)
{
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+ && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_hidden = 1;
}
previous_help_echo_string = help_echo_string;
+ help_echo_string = Qnil;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
last_window=window;
}
- note_mouse_movement (f, &msg.msg);
+ if (!note_mouse_movement (f, &msg.msg))
+ help_echo_string = previous_help_echo_string;
}
else
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
RECT rect;
- int h;
+ int left, top, h;
struct glyph *cursor_glyph;
HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
return;
/* Compute frame-relative coordinates for phys cursor. */
- rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+ get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
+ rect.left = left;
+ rect.top = top;
rect.bottom = rect.top + h;
rect.right = rect.left + w->phys_cursor_width;
x_catch_errors (dpy)
x_catch_errors_unwind (old_val)
x_check_errors (dpy, format)
+x_fully_uncatch_errors ()
+x_catching_errors ()
x_had_errors_p (dpy)
x_clear_errors (dpy)
x_uncatch_errors (dpy, count)