/* scrollbar implementation -- mswindows interface.
Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
- Copyright (C) 1994 Amdhal Corporation.
+ Copyright (C) 1994 Amdahl Corporation.
Copyright (C) 1995 Sun Microsystems, Inc.
Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>.
#define VERTICAL_SCROLLBAR_DRAG_HACK
static int vertical_drag_in_progress = 0;
+extern Lisp_Object mswindows_find_frame (HWND hwnd);
static void
mswindows_create_scrollbar_instance (struct frame *f, int vertical,
struct scrollbar_instance *sb)
{
int orientation;
-
+
sb->scrollbar_data = xnew_and_zero (struct mswindows_scrollbar_data);
-
+
if (vertical)
orientation = SBS_VERT;
else
orientation = SBS_HORZ;
-
+
SCROLLBAR_MSW_HANDLE (sb) =
CreateWindowEx(0, "SCROLLBAR", 0, orientation|WS_CHILD,
CW_USEDEFAULT, CW_USEDEFAULT,
static void
mswindows_free_scrollbar_instance (struct scrollbar_instance *sb)
{
- DestroyWindow (SCROLLBAR_MSW_HANDLE (sb));
- if (sb->scrollbar_data)
- xfree (sb->scrollbar_data);
+ if (sb->scrollbar_data)
+ {
+ DestroyWindow (SCROLLBAR_MSW_HANDLE (sb));
+ xfree (sb->scrollbar_data);
+ }
+}
+
+static void
+unshow_that_mofo (void *handle)
+{
+ ShowScrollBar ((HWND) handle, SB_CTL, 0);
}
static void
mswindows_release_scrollbar_instance (struct scrollbar_instance *sb)
{
- ShowScrollBar (SCROLLBAR_MSW_HANDLE (sb), SB_CTL, 0);
+ if (gc_in_progress)
+ /* #### way bogus! need to remove the offending call.
+ see mark_redisplay(). */
+ register_post_gc_action (unshow_that_mofo,
+ (void *) SCROLLBAR_MSW_HANDLE (sb));
+ else
+ ShowScrollBar (SCROLLBAR_MSW_HANDLE (sb), SB_CTL, 0);
SCROLLBAR_MSW_SIZE (sb) = 0;
}
int new_scrollbar_y)
{
int pos_changed = 0;
- int vert = GetWindowLong (SCROLLBAR_MSW_HANDLE (sb), GWL_STYLE) & SBS_VERT;
+ long styles = GetWindowLong (SCROLLBAR_MSW_HANDLE (sb), GWL_STYLE);
+ int vert = styles & SBS_VERT;
+
+ if (styles == 0) {
+ mswindows_output_last_error("GetWindowLong");
+ return;
+ }
#if 0
stderr_out ("[%d, %d], page = %d, pos = %d, inhibit = %d\n", new_minimum, new_maximum,
UPDATE_POS_FIELD (scrollbar_width);
UPDATE_POS_FIELD (scrollbar_height);
- if (pos_changed)
+ if (pos_changed)
{
MoveWindow(SCROLLBAR_MSW_HANDLE (sb),
new_scrollbar_x, new_scrollbar_y,
struct frame *f;
Lisp_Object win, frame;
struct scrollbar_instance *sb;
- SCROLLINFO scrollinfo;
- int vert = GetWindowLong (hwnd, GWL_STYLE) & SBS_VERT;
- int value;
+ long styles = GetWindowLong (hwnd, GWL_STYLE);
+ int vert = styles & SBS_VERT;
+
+ if (styles == 0) {
+ mswindows_output_last_error("GetWindowLong");
+ return;
+ }
sb = (struct scrollbar_instance *)GetWindowLong (hwnd, GWL_USERDATA);
- win = real_window (sb->mirror, 1);
- frame = XWINDOW (win)->frame;
- f = XFRAME (frame);
+ if (sb != NULL)
+ {
+ win = real_window (sb->mirror, 1);
+ /* "0 as the second parameter" refers to the call to real_window
+ above. This comment was taken from Ben's 21.5 code that differs
+ somewhat from this, I don't think the 21.4 code ever had a 0
+ there. #### we're still hitting an ABORT here with 0 as the
+ second parameter, although only occasionally. It seems that
+ sometimes we receive events for scrollbars that don't exist
+ anymore. I assume it must happen like this: The user does
+ something that causes a scrollbar to disappear (e.g. Alt-TAB,
+ causing recomputation of everything in the new frame) and then
+ immediately uses the mouse wheel, generating scrollbar events.
+ Both events get posted before we have a chance to process them,
+ and in processing the first, the scrollbar mentioned in the
+ second disappears. */
+ if (NILP (win))
+ return;
+ frame = XWINDOW (win)->frame;
+ f = XFRAME (frame);
+ }
+ else
+ {
+ /* I'm not sure if this is right, but its much better than
+ passing an HNWD to real_window() - which is what the previous
+ code did -- andyp */
+ frame = mswindows_find_frame (GetFocus());
+ f = XFRAME (frame);
+ win = FRAME_SELECTED_WINDOW (f);
+ }
/* SB_LINEDOWN == SB_CHARLEFT etc. This is the way they will
- always be - any Windows is binary compatible backward with
+ always be - any Windows is binary compatible backward with
old programs */
switch (code)
mswindows_enqueue_misc_user_event
(frame, vert ? Qscrollbar_line_down : Qscrollbar_char_right, win);
break;
-
+
case SB_LINEUP:
mswindows_enqueue_misc_user_event
(frame, vert ? Qscrollbar_line_up : Qscrollbar_char_left, win);
break;
-
+
case SB_PAGEDOWN:
mswindows_enqueue_misc_user_event
(win, vert ? Qscrollbar_page_down : Qscrollbar_page_right,
vert ? Qscrollbar_page_up : Qscrollbar_page_left,
vert ? Fcons (win, Qnil) : win);
break;
-
+
case SB_BOTTOM:
mswindows_enqueue_misc_user_event
(frame, vert ? Qscrollbar_to_bottom : Qscrollbar_to_right, win);
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
- scrollinfo.cbSize = sizeof(SCROLLINFO);
- scrollinfo.fMask = SIF_ALL;
- GetScrollInfo (hwnd, SB_CTL, &scrollinfo);
- vertical_drag_in_progress = vert;
+ {
+ int pos;
+ SCROLLINFO scrollinfo;
+ scrollinfo.cbSize = sizeof(SCROLLINFO);
+ scrollinfo.fMask = SIF_ALL;
+ GetScrollInfo (hwnd, SB_CTL, &scrollinfo);
+ vertical_drag_in_progress = vert;
#ifdef VERTICAL_SCROLLBAR_DRAG_HACK
if (vert && (scrollinfo.nTrackPos > scrollinfo.nPos))
/* new buffer position =
* ((text remaining in buffer at start of drag) *
* (amount that the thumb has been moved) /
* (space that remained past end of the thumb at start of drag)) */
- value = (int)
+ pos = (int)
(scrollinfo.nPos
+ (((double)
(scrollinfo.nMax - scrollinfo.nPos)
- 2; /* ensure that the last line doesn't disappear off screen */
else
#endif
- value = scrollinfo.nTrackPos;
+ pos = scrollinfo.nTrackPos;
mswindows_enqueue_misc_user_event
(frame,
vert ? Qscrollbar_vertical_drag : Qscrollbar_horizontal_drag,
- Fcons (win, make_int (value)));
+ Fcons (win, make_int (pos)));
+ }
break;
case SB_ENDSCROLL:
#ifdef VERTICAL_SCROLLBAR_DRAG_HACK
- if (vertical_drag_in_progress)
+ if (vertical_drag_in_progress && sb)
/* User has just dropped the thumb - finally update it */
SetScrollInfo (SCROLLBAR_MSW_HANDLE (sb), SB_CTL,
&SCROLLBAR_MSW_INFO (sb), TRUE);
}
}
+static int
+can_scroll (struct scrollbar_instance* scrollbar)
+{
+ return scrollbar != NULL
+ && IsWindowVisible (SCROLLBAR_MSW_HANDLE (scrollbar))
+ && IsWindowEnabled (SCROLLBAR_MSW_HANDLE (scrollbar));
+}
+
+int
+mswindows_handle_mousewheel_event (Lisp_Object frame, int keys, int delta,
+ POINTS where)
+{
+ int hasVertBar, hasHorzBar; /* Indicates presence of scroll bars */
+ unsigned wheelScrollLines = 0; /* Number of lines per wheel notch */
+ Lisp_Object win, corpore, sano;
+ struct window_mirror *mirror;
+ int mene, _mene, tekel, upharsin;
+ Bufpos mens, sana;
+ Charcount in;
+ struct window *needle_in_haystack = 0;
+ POINT donde_esta;
+
+ donde_esta.x = where.x;
+ donde_esta.y = where.y;
+
+ /* Find the window to scroll */
+
+ /* The mouse event could actually occur outside of the emacs
+ frame. */
+ if (ScreenToClient (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
+ &donde_esta) != 0)
+ {
+ /* stderr_out ("donde_esta: %d %d\n", donde_esta.x, donde_esta.y); */
+ pixel_to_glyph_translation (XFRAME (frame), donde_esta.x, donde_esta.y,
+ &mene, &_mene, &tekel, &upharsin,
+ &needle_in_haystack,
+ &mens, &sana, &in, &corpore, &sano);
+
+ if (needle_in_haystack)
+ {
+ XSETWINDOW (win, needle_in_haystack);
+ /* stderr_out ("found needle\n");
+ debug_print (win); */
+ }
+ }
+
+ if (!needle_in_haystack)
+ {
+ win = FRAME_SELECTED_WINDOW (XFRAME (frame));
+ needle_in_haystack = XWINDOW (win);
+ }
+
+ mirror = find_window_mirror (needle_in_haystack);
+
+ /* Check that there is something to scroll */
+ hasVertBar = can_scroll (mirror->scrollbar_vertical_instance);
+ hasHorzBar = can_scroll (mirror->scrollbar_horizontal_instance);
+ if (!hasVertBar && !hasHorzBar)
+ return FALSE;
+
+ /* No support for panning and zooming, so ignore */
+ if (keys & (MK_SHIFT | MK_CONTROL))
+ return FALSE;
+
+ /* Get the number of lines per wheel delta */
+ SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &wheelScrollLines, 0);
+
+ /* Calculate the amount to scroll */
+ if (wheelScrollLines == WHEEL_PAGESCROLL)
+ {
+ /* Scroll by a page */
+ Lisp_Object function;
+ if (hasVertBar)
+ function = delta > 0 ? Qscrollbar_page_up : Qscrollbar_page_down;
+ else
+ function = delta > 0 ? Qscrollbar_page_left : Qscrollbar_page_right;
+ mswindows_enqueue_misc_user_event (frame, function, Fcons (win, Qnil));
+ }
+ else /* Scroll by a number of lines */
+ {
+ /* Calc the number of lines to scroll */
+ int toScroll = MulDiv (delta, wheelScrollLines, WHEEL_DELTA);
+
+ /* Do the scroll */
+ Lisp_Object function;
+ if (hasVertBar)
+ function = delta > 0 ? Qscrollbar_line_up : Qscrollbar_line_down;
+ else
+ function = delta > 0 ? Qscrollbar_char_left : Qscrollbar_char_right;
+ if (toScroll < 0)
+ toScroll = -toScroll;
+ while (toScroll--)
+ mswindows_enqueue_misc_user_event (frame, function, win);
+ }
+
+ return TRUE;
+}
+
#ifdef MEMORY_USAGE_STATS
static int