📄 scrollbar_event.c
字号:
return; } sb->request_motion = motion; sb->request_offset = request_offset; /* if undoing, restore view_start from undo_mark, else compute it */ /* First save view_start as old_view_start. When if the newly */ /* computed view_start is different, set the bubble_modified flag */ /* so that the next scrollbar_paint erases the old bubble. */ sb->old_view_start = sb->view_start; if (undoing) { sb->request_offset = sb->undo_request_offset; sb->view_start = sb->undo_mark; sb->undo_mark = sb->old_view_start; sb->undo_request_offset = old_request_offset; } else compute_new_view_start(sb, bar_length); if (sb->view_start != sb->old_view_start) sb->bubble_modified = TRUE; (void)win_post_id_and_arg(sb->notify_client, SCROLL_REQUEST, NOTIFY_SAFE, (char *)sb, NOTIFY_COPY_NULL, NOTIFY_RELEASE_NULL);}/**************************************************************************//* compute_new_view_start *//* In the relative motions, we take into account that the scrollbar's *//* view_start, view_length and object_length are in client units, which *//* may be other than pixels -- chars or lines, for example. *//**************************************************************************/static voidcompute_new_view_start(sb, bar_length)register scrollbar_handle sb;int bar_length;{ int align_to_max = FALSE; int scrolling_up = TRUE; int desired_scroll = 0; int new_offset = sb->view_start; /*note use of int, not unsigned*/ int min_offset = 0; int max_offset = sb->object_length; int margin_offset = sb->normalize_margin; int gap_offset = sb->gap; int line_offset = sb->line_height; /* If gap not yet set, use margin. */ if (gap_offset==SCROLLBAR_INVALID_LENGTH) gap_offset = margin_offset; switch (sb->request_motion) { case SCROLL_ABSOLUTE: { /* factor button lengths out; save bar_length for normalization */ int offset_into_bar = sb->request_offset - sb->button_length; int bar_size = bar_length - 2*sb->button_length; int end_point_area = sb->end_point_area; int bubble_top_offset; int bubble_extent; struct rect bubble; if (end_point_area > bar_size/2) end_point_area = bar_size/2; /* adjust for top/bottom gravity */ if (offset_into_bar <= end_point_area) { new_offset = 0; break; } else if (bar_size - offset_into_bar <= end_point_area) { new_offset = max_offset - (3*(sb->view_length/4)); /* desired_scroll = -(sb->line_height); */ break; } /* figure where the top of the bubble should go */ (void)scrollbar_compute_bubble_rect(sb, &bubble); if (sb->horizontal) bubble_extent = bubble.r_width; else bubble_extent = bubble.r_height; bubble_top_offset = offset_into_bar - (bubble_extent / 2); if (bubble_top_offset < 0) bubble_top_offset = 0; /* finally, compute the new view_start */ new_offset = ((double)sb->object_length * bubble_top_offset) / bar_size; break; } case SCROLL_FORWARD: /* POINT_TO_MIN */ desired_scroll = sb->request_offset; break; case SCROLL_BACKWARD: /* MIN_TO_POINT */ desired_scroll = -(sb->request_offset); scrolling_up = FALSE; break; case SCROLL_MAX_TO_POINT: if (!sb->advanced_mode) { sb->request_offset = bar_length - sb->request_offset; sb->request_motion = SCROLL_FORWARD; } desired_scroll = bar_length - sb->request_offset; align_to_max = TRUE; break; case SCROLL_POINT_TO_MAX: if (!sb->advanced_mode) { sb->request_offset = bar_length - sb->request_offset; sb->request_motion = SCROLL_BACKWARD; } desired_scroll = -(bar_length - sb->request_offset); align_to_max = TRUE; scrolling_up = FALSE; break; case SCROLL_PAGE_FORWARD: if (!sb->advanced_mode) { sb->request_offset = bar_length; sb->request_motion = SCROLL_FORWARD; } new_offset += sb->view_length; break; case SCROLL_PAGE_BACKWARD: if (!sb->advanced_mode) { sb->request_offset = bar_length; sb->request_motion = SCROLL_BACKWARD; } new_offset -= sb->view_length; scrolling_up = FALSE; break; case SCROLL_LINE_FORWARD: desired_scroll = sb->line_height; if (sb->use_grid && !new_offset) /* special case for top of object */ desired_scroll += (margin_offset - gap_offset); if (!sb->advanced_mode) { sb->request_offset = desired_scroll; sb->request_motion = SCROLL_FORWARD; } break; case SCROLL_LINE_BACKWARD: if (!sb->advanced_mode) { sb->request_offset = sb->line_height; sb->request_motion = SCROLL_BACKWARD; } desired_scroll = -(sb->line_height); scrolling_up = FALSE; break; } if (desired_scroll) /* int cast rqd due to c's brain damaged mult! */ new_offset += (desired_scroll * (int)sb->view_length) / bar_length;/* * Grid Normalization: * * +---------------------------------------+ margin_offset * +---------------------------------------+ ------- * | | | * | | line_offset * | | | * |.......................................| ------- * | | * | | *------|---------------------------------------|---- new_offset * |.......................................| * | | * | | * * * We assume the view space is regularly divided by cells of equal size * (line_height) with an initial gap and external margin, both measured * in pixels. Note that the line_height is assumed to contain the * inter-object white space gap. This is because the line ht is used * as the amount to move on a line up/down scroll. * * Normalization simply "rounds" the new_offset to be at an integral * number of line_heights from the start of the view. The "rounding * rule" is to round up to the next line when scrolling down, * and round down when scrolling up. This preserves partial objects: * A motion to a partial object will not inadvertantly scroll it out * of the view window. * * Fine point: Note that we do not subtract margin from the new_offset * when calculating the number of lines new_offset corresponds to. This * is so that a point within margin of line "n" will show that line, * not line n-1. */ if (/*sb->line_height &&*/ sb->use_grid) { if (sb->view_length != bar_length) { margin_offset = (margin_offset * sb->view_length) / bar_length; line_offset = (line_offset * sb->view_length) / bar_length; gap_offset = (gap_offset * sb->view_length) / bar_length; } if (line_offset) { min_offset = margin_offset; max_offset = (max_offset - margin_offset) / line_offset; max_offset = (max_offset * line_offset) + margin_offset - gap_offset; if (align_to_max) new_offset += sb->view_length; if (!scrolling_up) new_offset += line_offset - 1; new_offset = (new_offset - margin_offset + gap_offset) / line_offset; new_offset = (new_offset * line_offset) + margin_offset - gap_offset; if (align_to_max) new_offset -= sb->view_length; }#ifdef notdef if (line_offset) { min_offset = margin_offset; max_offset = ((max_offset-margin_offset)/line_offset) * line_offset; if (align_to_max) new_offset += sb->view_length; if (!scrolling_up) new_offset += line_offset - 1; new_offset = (new_offset /*-margin*/ / line_offset) * line_offset; if (align_to_max) new_offset -= sb->view_length; }#endif } if (new_offset <= min_offset) new_offset = 0; else if (new_offset > max_offset) new_offset = max_offset; sb->view_start = new_offset;}/**************************************************************************//* scrollbar_resize *//**************************************************************************//*ARGSUSED*/static voidscrollbar_resize(sb)scrollbar_handle sb;{}/************************************************************************//* timer notify proc *//************************************************************************//*ARGSUSED*/static Notify_valuescrollbar_timed_out(client, which)Notify_client client;int which;{ scrollbar_t_on = TRUE; post_scroll((scrollbar_handle)(LINT_CAST(client)), &scrollbar_t_event, scrollbar_t_motion, FALSE); return NOTIFY_DONE;}static voidscrollbar_timer_start(sb, event, motion)scrollbar_handle sb;Event *event;Scroll_motion motion;{ int tenths, usecs, secs; tenths = sb->delay; if (!tenths) return; usecs = (tenths % 10)*100000; secs = tenths / 10; scrollbar_timer.it_value.tv_usec = usecs; scrollbar_timer.it_value.tv_sec = secs; scrollbar_timer.it_interval.tv_usec = 1; scrollbar_timer.it_interval.tv_sec = 0; scrollbar_t_event = *event; scrollbar_t_motion = motion; (void)notify_set_itimer_func((Notify_client)sb, scrollbar_timed_out, ITIMER_REAL, &scrollbar_timer, (struct itimerval *)NULL);}static voidscrollbar_timer_stop(sb)scrollbar_handle sb;{ scrollbar_t_on = FALSE; (void)notify_set_itimer_func((Notify_client)sb, scrollbar_timed_out, ITIMER_REAL, (struct itimerval *)NULL, (struct itimerval *)NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -