Exemple #1
0
static void
draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which)
{
  struct frame *f = XFRAME (WINDOW_FRAME (w));
  struct draw_fringe_bitmap_params p;
  struct fringe_bitmap *fb;
  int period;
  int face_id = DEFAULT_FACE_ID;
  int offset, header_line_height;

  p.overlay_p = (overlay & 1) == 1;
  p.cursor_p = (overlay & 2) == 2;

  if (which != NO_FRINGE_BITMAP)
    {
      offset = 0;
    }
  else if (left_p)
    {
      which = row->left_fringe_bitmap;
      face_id = row->left_fringe_face_id;
      offset = row->left_fringe_offset;
    }
  else
    {
      which = row->right_fringe_bitmap;
      face_id = row->right_fringe_face_id;
      offset = row->right_fringe_offset;
    }

  if (face_id == DEFAULT_FACE_ID)
    {
      Lisp_Object face = fringe_faces[which];
      face_id = NILP (face) ? lookup_named_face (f, Qfringe, 0)
	: lookup_derived_face (f, face, FRINGE_FACE_ID, 0);
      if (face_id < 0)
	face_id = FRINGE_FACE_ID;
    }

  fb = get_fringe_bitmap_data (which);

  period = fb->period;

  /* Convert row to frame coordinates.  */
  p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;

  p.which = which;
  p.bits = fb->bits;
  p.wd = fb->width;

  p.h = fb->height;
  p.dh = (period > 0 ? (p.y % period) : 0);
  p.h -= p.dh;

  /* Adjust y to the offset in the row to start drawing the bitmap.  */
  switch (fb->align)
    {
    case ALIGN_BITMAP_CENTER:
      p.y += (row->height - p.h) / 2;
      break;
    case ALIGN_BITMAP_BOTTOM:
      p.y += (row->visible_height - p.h);
      break;
    case ALIGN_BITMAP_TOP:
      break;
    }

  p.face = FACE_FROM_ID (f, face_id);

  if (p.face == NULL)
    {
      /* This could happen after clearing face cache.
	 But it shouldn't happen anymore.  ++kfs */
      return;
    }

  PREPARE_FACE_FOR_DISPLAY (f, p.face);

  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
     the fringe.  */
  p.bx = -1;
  header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
  p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
  p.ny = row->visible_height;
  if (left_p)
    {
      int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
      int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
				   ? LEFT_MARGIN_AREA
				   : TEXT_AREA));
      if (p.wd > wd)
	p.wd = wd;
      p.x = x - p.wd - (wd - p.wd) / 2;

      if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
	{
	  /* If W has a vertical border to its left, don't draw over it.  */
	  wd -= ((!WINDOW_LEFTMOST_P (w)
		  && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
		 ? 1 : 0);
	  p.bx = x - wd;
	  p.nx = wd;
	}
    }
  else
    {
      int x = window_box_right (w,
				(WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
				 ? RIGHT_MARGIN_AREA
				 : TEXT_AREA));
      int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
      if (p.wd > wd)
	p.wd = wd;
      p.x = x + (wd - p.wd) / 2;
      /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
	 the fringe.  */
      if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
	{
	  p.bx = x;
	  p.nx = wd;
	}
    }

  FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
}
Exemple #2
0
void viper_kmio_dispatch(gint32 keystroke,MEVENT *mouse_event)
{
   extern VIPER            *viper;
   static WINDOW           *event_window=NULL;
   static MEVENT           previous_mouse_event;
   static VIPER_WKEY_FUNC  func;
   static gint             event_mode=0;
   VIPER_KMIO_HOOK         kmio_dispatch_hook;
   gint                    beg_x,beg_y;
   gint                    max_x,max_y;
   MEVENT                  *new_mouse=NULL;     /* strictly for      */
   MEVENT                  *old_mouse=NULL;     /* for readability   */
#if !defined(_NO_GPM) && defined(__linux)
	extern int        		gpm_fd;
#endif

   // run the dispatch pre-processing hook
   if(viper->kmio_dispatch_hook[KMIO_HOOK_ENTER] != NULL)
   {
      kmio_dispatch_hook=viper->kmio_dispatch_hook[KMIO_HOOK_ENTER];
      keystroke=kmio_dispatch_hook(keystroke);
   }

   if(keystroke == -1) return;

   if(keystroke==KEY_RESIZE)
   {
      viper_event_run(VIPER_EVENT_BROADCAST,"term-resized");
      /* todo event handle for screen window instead  */
      viper_screen_redraw(REDRAW_ALL | REDRAW_BACKGROUND);
   }

   if(keystroke==KEY_MOUSE && mouse_event!=NULL)
   {
      new_mouse=mouse_event;
      old_mouse=&previous_mouse_event;

      if((new_mouse->bstate & REPORT_MOUSE_POSITION)
          && event_mode==EVENTMODE_MOVE)
      {
         viper_mvwin_rel(event_window,new_mouse->x-old_mouse->x,
            new_mouse->y-old_mouse->y);
         memcpy(old_mouse,new_mouse,sizeof(MEVENT));
      }

      if((new_mouse->bstate & REPORT_MOUSE_POSITION)
         && event_mode==EVENTMODE_RESIZE)
      {
         viper_wresize_rel(event_window,new_mouse->x-old_mouse->x,
            new_mouse->y-old_mouse->y);
         memcpy(old_mouse,new_mouse,sizeof(MEVENT));
      }

      /* check for a button press and a window hit */
      if((new_mouse->bstate & BUTTON1_PRESSED) && event_mode==EVENTMODE_IDLE)
      {
         event_window=viper_deck_hit_test(new_mouse->x,new_mouse->y);
         if(event_window!=NULL)
         {
            viper_window_set_top(event_window);
            memcpy(old_mouse,new_mouse,sizeof(MEVENT));
            getbegyx(WINDOW_FRAME(event_window),beg_y,beg_x);
            getmaxyx(WINDOW_FRAME(event_window),max_y,max_x);
            if(new_mouse->x==(beg_x+max_x-1) &&
               new_mouse->y==(beg_y+max_y)-1) event_mode=EVENTMODE_RESIZE;
            else event_mode=EVENTMODE_MOVE;
         }
         else event_mode=EVENTMODE_IDLE;
      }

     if(new_mouse->bstate & BUTTON1_RELEASED)
      {
         if(!(new_mouse->bstate & REPORT_MOUSE_POSITION))
         {
            if(event_mode==EVENTMODE_MOVE) viper_mvwin_rel(event_window,
               new_mouse->x-old_mouse->x,new_mouse->y-old_mouse->y);

            /* resize window  */
            if(event_mode==EVENTMODE_RESIZE)
            {
               viper_wresize_rel(event_window,new_mouse->x-old_mouse->x,
                  new_mouse->y-old_mouse->y);
               viper_screen_redraw(REDRAW_ALL);
            }
         }

         event_window=NULL;
         event_mode=EVENTMODE_IDLE;
      }

      if(new_mouse->bstate & BUTTON1_CLICKED)
      {
         event_window=viper_deck_hit_test(new_mouse->x,new_mouse->y);
         if(event_window!=NULL)
         {
            viper_window_set_top(event_window);
            viper_window_redraw(event_window);

            getbegyx(WINDOW_FRAME(event_window),beg_y,beg_x);
            getmaxyx(WINDOW_FRAME(event_window),max_y,max_x);
            if(new_mouse->x==(beg_x+max_x-2) && new_mouse->y==beg_y)
            {
               viper_window_close(event_window);
               keystroke=-1;
            }
            if(new_mouse->x==(beg_x+max_x-4) && new_mouse->y==beg_y)
            {
               viper_window_hide(event_window);
               viper_deck_cycle(VECTOR_BOTTOM_TO_TOP);
               keystroke=-1;
            }
         }
         event_window=NULL;
         event_mode=EVENTMODE_IDLE;
      }

      if(new_mouse->bstate & BUTTON1_DOUBLE_CLICKED)
      {
         event_window=viper_deck_hit_test(new_mouse->x,new_mouse->y);
         if(event_window!=NULL)
         {
            viper_window_set_top(event_window);
            viper_window_redraw(event_window);
         }

         event_window=NULL;
         event_mode=EVENTMODE_IDLE;
      }
   }

   // run the post-processing dispatch hook
   if(viper->kmio_dispatch_hook[KMIO_HOOK_LEAVE] != NULL)
   {
      kmio_dispatch_hook=viper->kmio_dispatch_hook[KMIO_HOOK_LEAVE];
      keystroke=kmio_dispatch_hook(keystroke);
   }

   // pass keystroke on to toplevel window
   if(keystroke != KEY_RESIZE && keystroke != -1)
   {
      func=viper_window_get_key_func(TOPMOST_WINDOW);
      if(func!=NULL) func(keystroke,(gpointer)TOPMOST_WINDOW);
   }

#if !defined(_NO_GPM) && defined(__linux)
	if(gpm_fd>0)
	{
   	viper_kmio_show_mouse(new_mouse);
   	viper_screen_redraw(REDRAW_ALL);
	}
#endif



}
Exemple #3
0
/*
 * This is the only callback provided for horizontal scrollbars.  It
 * should be able to handle all of the scrollbar events in
 * scroll_action (see lwlib.h).  The client data will be of type
 * scroll_event (see lwlib.h). */
static void
x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id,
					XtPointer client_data)
{
  scroll_event *data = (scroll_event *) client_data;
  struct device *d = get_device_from_display (XtDisplay (widget));
  struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
  Lisp_Object win, frame;
  struct window_mirror *mirror;

  if (!f)
    return;

  mirror = find_scrollbar_window_mirror (f, id);
  if (!mirror)
    return;

  win = real_window (mirror, 1);

  if (NILP (win))
    return;
  frame = WINDOW_FRAME (XWINDOW (win));

  /* It seems that this is necessary whenever signal_special_Xt_user_event()
     is called.  #### Why??? */
  DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);

  switch (data->action)
    {
    case SCROLLBAR_LINE_UP:
      signal_special_Xt_user_event (frame, Qscrollbar_char_left, win);
      break;
    case SCROLLBAR_LINE_DOWN:
      signal_special_Xt_user_event (frame, Qscrollbar_char_right, win);
      break;
    case SCROLLBAR_PAGE_UP:
      signal_special_Xt_user_event (frame, Qscrollbar_page_left, win);
      break;
    case SCROLLBAR_PAGE_DOWN:
      signal_special_Xt_user_event (frame, Qscrollbar_page_right, win);
      break;
    case SCROLLBAR_TOP:
      signal_special_Xt_user_event (frame, Qscrollbar_to_left, win);
      break;
    case SCROLLBAR_BOTTOM:
      signal_special_Xt_user_event (frame, Qscrollbar_to_right, win);
      break;
    case SCROLLBAR_CHANGE:
      inhibit_slider_size_change = 0;
      break;
    case SCROLLBAR_DRAG:
      inhibit_slider_size_change = 1;
      /* #### Fix the damn toolkit code so they all work the same way.
         Lucid is the one mostly wrong.*/
#if defined (LWLIB_SCROLLBARS_LUCID) || defined (LWLIB_SCROLLBARS_ATHENA3D)
      signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag,
				    (Fcons
				     (win, make_int (data->slider_value))));
#else
      signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag,
				    (Fcons
				     (win,
				      make_int (data->slider_value - 1))));
#endif
      break;
    default:
      break;
    }
}
Exemple #4
0
static void
draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which)
{
  struct frame *f = XFRAME (WINDOW_FRAME (w));
  struct draw_fringe_bitmap_params p;
  struct fringe_bitmap *fb;
  int period;
  int face_id = DEFAULT_FACE_ID;
  int offset, header_line_height;

  p.overlay_p = (overlay & 1) == 1;
  p.cursor_p = (overlay & 2) == 2;

  if (which != NO_FRINGE_BITMAP)
    {
      offset = 0;
    }
  else if (left_p)
    {
      which = row->left_fringe_bitmap;
      face_id = row->left_fringe_face_id;
      offset = row->left_fringe_offset;
    }
  else
    {
      which = row->right_fringe_bitmap;
      face_id = row->right_fringe_face_id;
      offset = row->right_fringe_offset;
    }

  if (face_id == DEFAULT_FACE_ID)
    {
      Lisp_Object face = fringe_faces[which];
      face_id = NILP (face) ? lookup_named_face (f, Qfringe, false)
	: lookup_derived_face (f, face, FRINGE_FACE_ID, 0);
      if (face_id < 0)
	face_id = FRINGE_FACE_ID;
    }

  fb = get_fringe_bitmap_data (which);

  period = fb->period;

  /* Convert row to frame coordinates.  */
  p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;

  p.which = which;
  p.bits = fb->bits;
  p.wd = fb->width;

  p.h = fb->height;
  p.dh = (period > 0 ? (p.y % period) : 0);
  p.h -= p.dh;

  /* Adjust y to the offset in the row to start drawing the bitmap.  */
  switch (fb->align)
    {
    case ALIGN_BITMAP_CENTER:
      p.y += (row->height - p.h) / 2;
      break;
    case ALIGN_BITMAP_BOTTOM:
      p.y += (row->visible_height - p.h);
      break;
    case ALIGN_BITMAP_TOP:
      break;
    }

  p.face = FACE_FROM_ID_OR_NULL (f, face_id);
  if (p.face == NULL)
    {
      /* This could happen after clearing face cache.
	 But it shouldn't happen anymore.  ++kfs */
      return;
    }

  prepare_face_for_display (f, p.face);

  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
     the fringe.  */
  p.bx = -1;
  header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
  p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
  p.ny = row->visible_height;
  if (left_p)
    {
      int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
      int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
				   ? LEFT_MARGIN_AREA
				   : TEXT_AREA));
      if (p.wd > wd)
	p.wd = wd;
      p.x = x - p.wd - (wd - p.wd) / 2;

      if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
	{
	  /* If W has a vertical border to its left, don't draw over it.  */
	  wd -= ((!WINDOW_LEFTMOST_P (w)
		  /* This could be wrong when we allow window local
		     right dividers - but the window on the left is hard
		     to get.  */
		  && !FRAME_RIGHT_DIVIDER_WIDTH (f)
		  && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
		  /* But don't reduce the fringe width if the window
		     has a left margin, because that means we are not
		     in danger of drawing over the vertical border,
		     and OTOH leaving out that one pixel leaves behind
		     traces of the cursor, if it was in column zero
		     before drawing non-empty margin area.  */
		  && w->left_margin_cols == 0)
		 ? 1 : 0);
	  p.bx = x - wd;
	  p.nx = wd;
	}
    }
  else
    {
      int x = window_box_right (w,
				(WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
				 ? RIGHT_MARGIN_AREA
				 : TEXT_AREA));
      int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
      if (p.wd > wd)
	p.wd = wd;
      p.x = x + (wd - p.wd) / 2;
      /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
	 the fringe.  */
      if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
	{
	  p.bx = x;
	  p.nx = wd;
	}
    }

  if (p.x >= WINDOW_BOX_LEFT_EDGE_X (w)
      && (p.x + p.wd) <= WINDOW_BOX_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w))
    FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
}
Exemple #5
0
/*
 * This is the only callback provided for vertical scrollbars.  It
 * should be able to handle all of the scrollbar events in
 * scroll_action (see lwlib.h).  The client data will be of type
 * scroll_event (see lwlib.h). */
static void
x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id,
				      XtPointer client_data)
{
  /* This function can GC */
  scroll_event *data = (scroll_event *) client_data;
  struct device *d = get_device_from_display (XtDisplay (widget));
  struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
  Lisp_Object win, frame;
  struct scrollbar_instance *instance;
  struct window_mirror *mirror;

  if (!f)
    return;

  mirror = find_scrollbar_window_mirror (f, id);
  if (!mirror)
    return;

  win = real_window (mirror, 1);

  if (NILP (win))
    return;
  instance = mirror->scrollbar_vertical_instance;
  frame = WINDOW_FRAME (XWINDOW (win));

  /* It seems that this is necessary whenever signal_special_Xt_user_event()
     is called.  #### Why??? */
  DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);

  switch (data->action)
    {
    case SCROLLBAR_LINE_UP:
      signal_special_Xt_user_event (frame, Qscrollbar_line_up, win);
      break;

    case SCROLLBAR_LINE_DOWN:
      signal_special_Xt_user_event (frame, Qscrollbar_line_down, win);
      break;

      /* The Athena scrollbar paging behavior is that of xterms.
         Depending on where you click the size of the page varies.
         Motif always does a standard Emacs page. */
    case SCROLLBAR_PAGE_UP:
#if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
    !defined (LWLIB_SCROLLBARS_ATHENA3D)
      {
	double tmp = ((double) data->slider_value /
		      (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height);
	double line = tmp *
	  (double) window_displayed_height (XWINDOW (win));

	if (line > -1.0)
	  line = -1.0;
	signal_special_Xt_user_event (frame, Qscrollbar_page_up,
				      Fcons (win, make_int ((int) line)));
      }
#else
      signal_special_Xt_user_event (frame, Qscrollbar_page_up,
				    Fcons (win, Qnil));
#endif
      break;

    case SCROLLBAR_PAGE_DOWN:
#if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
    !defined (LWLIB_SCROLLBARS_ATHENA3D)
      {
	double tmp = ((double) data->slider_value /
		      (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height);
	double line = tmp *
	  (double) window_displayed_height (XWINDOW (win));

	if (SCROLLBAR_X_POS_DATA(instance).maximum >
	    (SCROLLBAR_X_POS_DATA(instance).slider_size + SCROLLBAR_X_POS_DATA(instance).slider_position))
	  {
	    if (line < 1.0)
	      line = 1.0;
	    signal_special_Xt_user_event (frame, Qscrollbar_page_down,
					  Fcons (win,
						 make_int ((int) line)));
	  }
      }
#else
      signal_special_Xt_user_event (frame, Qscrollbar_page_down,
				    Fcons (win, Qnil));
#endif
      break;

    case SCROLLBAR_TOP:
      signal_special_Xt_user_event (frame, Qscrollbar_to_top, win);
      break;

    case SCROLLBAR_BOTTOM:
      signal_special_Xt_user_event (frame, Qscrollbar_to_bottom, win);
      break;


    case SCROLLBAR_CHANGE:
      inhibit_slider_size_change = 0;
#if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
      vertical_drag_in_progress = 0;
      SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value;
      SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) =
	XINT (Fwindow_start (win));
#else
      stupid_vertical_scrollbar_drag_hack = 0;
#endif
      break;

    case SCROLLBAR_DRAG:
      {
	int value;

	inhibit_slider_size_change = 1;

#if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
	/* Doing drags with Motif-like scrollbars is a mess, since we
	   want to avoid having the window position jump when you
	   first grab the scrollbar, but we also want to ensure that
	   you can scroll all the way to the top or bottom of the
	   buffer.  This can all be replaced with something sane when
	   we get line-based scrolling. */

	vertical_drag_in_progress = 1;

	if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) < 0)
	  {
	    SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value;
	    SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) =
	      XINT (Fwindow_start (win));
	  }

	/* Could replace this piecewise linear scrolling with a
	   quadratic through the three points, but I'm not sure that
	   would feel any nicer in practice. */
	if (data->slider_value < SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))
	  {
	    /* We've dragged up; slide linearly from original position to
	       window-start=data.minimum, slider-value=data.minimum. */

	    if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
		<= SCROLLBAR_X_POS_DATA (instance).minimum)
	      {
		/* shouldn't get here, but just in case */
		value = SCROLLBAR_X_POS_DATA (instance).minimum;
	      }
	    else
	      {
		value = (int)
		  (SCROLLBAR_X_POS_DATA (instance).minimum
		   + (((double)
		       (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)
			- SCROLLBAR_X_POS_DATA (instance).minimum)
		       * (data->slider_value -
			  SCROLLBAR_X_POS_DATA (instance).minimum))
		      / (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
			 - SCROLLBAR_X_POS_DATA (instance).minimum)));
	      }
	  }
	else
	  {
	    /* We've dragged down; slide linearly from original position to
	       window-start=data.maximum, slider-value=data.maximum. */

	    if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
		>= (SCROLLBAR_X_POS_DATA (instance).maximum -
		    SCROLLBAR_X_POS_DATA (instance).slider_size))
	      {
		/* avoid divide by zero */
		value = SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance);
	      }
	    else
	      {
		value = (int)
		  (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)
		   + (((double)
		       (SCROLLBAR_X_POS_DATA (instance).maximum
			- SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance))
		       * (data->slider_value
			  - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)))
		      / (SCROLLBAR_X_POS_DATA (instance).maximum
			 - SCROLLBAR_X_POS_DATA (instance).slider_size
			 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))));
	      }
	  }
#else
	stupid_vertical_scrollbar_drag_hack = 0;
	value = data->slider_value;
#endif

	if (value >= SCROLLBAR_X_POS_DATA (instance).maximum)
	  value = SCROLLBAR_X_POS_DATA (instance).maximum - 1;
	if (value < SCROLLBAR_X_POS_DATA (instance).minimum)
	  value = SCROLLBAR_X_POS_DATA (instance).minimum;

	signal_special_Xt_user_event (frame, Qscrollbar_vertical_drag,
				      Fcons (win, make_int (value)));
      }
      break;

    }
}