Reduce redraw area for selection set/change/clear.

This commit is contained in:
Michael Drake 2013-03-22 18:01:02 +00:00
parent b603cafbaa
commit 70fbca3606

View File

@ -459,7 +459,6 @@ static bool textarea_select(struct textarea *ta, int b_start, int b_end,
int swap;
bool pre_existing_selection = (ta->sel_start != -1);
struct textarea_msg msg;
int line_start = 0, line_end = 0;
if (b_start == b_end) {
textarea_clear_selection(ta);
@ -483,18 +482,29 @@ static bool textarea_select(struct textarea *ta, int b_start, int b_end,
msg.data.redraw.x1 = ta->vis_width - ta->border_width -
((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
if (force_redraw || !pre_existing_selection ||
(ta->sel_start != b_start && ta->sel_end != b_end)) {
/* Asked to redraw everything, or there's a new selection, or
* both ends of the selection have moved */
if (force_redraw) {
/* Asked to redraw everything */
msg.data.redraw.y0 = ta->border_width;
msg.data.redraw.y1 = ta->vis_height - ta->border_width -
((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
} else {
/* Redraw to cover change in selection start or change in
* selection end */
/* Try to minimise redraw region */
unsigned int b_low, b_high;
if (ta->sel_start != b_start) {
int line_start = 0, line_end = 0;
if (!pre_existing_selection) {
/* There's a new selection */
b_low = b_start;
b_high = b_end;
} else if (ta->sel_start != b_start && ta->sel_end != b_end) {
/* Both ends of the selection have moved */
b_low = (ta->sel_start < b_start) ?
ta->sel_start : b_start;
b_high = (ta->sel_end > b_end) ?
ta->sel_end : b_end;
} else if (ta->sel_start != b_start) {
/* Selection start changed */
if ((signed)ta->sel_start < b_start) {
b_low = ta->sel_start;
@ -503,6 +513,7 @@ static bool textarea_select(struct textarea *ta, int b_start, int b_end,
b_low = b_start;
b_high = ta->sel_start;
}
} else {
/* Selection end changed */
if ((signed)ta->sel_end < b_end) {
@ -514,6 +525,7 @@ static bool textarea_select(struct textarea *ta, int b_start, int b_end,
}
}
/* Find redraw start/end lines */
for (line_end = 0; line_end < ta->line_count - 1; line_end++)
if (ta->lines[line_end + 1].b_start > b_low) {
line_start = line_end;
@ -523,6 +535,7 @@ static bool textarea_select(struct textarea *ta, int b_start, int b_end,
if (ta->lines[line_end + 1].b_start > b_high)
break;
/* Set vertical redraw range */
msg.data.redraw.y0 = max(ta->border_width,
ta->line_height * line_start +
ta->text_y_offset - ta->scroll_y);
@ -2677,22 +2690,37 @@ textarea_mouse_status textarea_mouse_action(struct textarea *ta,
bool textarea_clear_selection(struct textarea *ta)
{
struct textarea_msg msg;
int line_end, line_start = 0;
if (ta->sel_start == -1)
/* No selection to clear */
return false;
/* Find selection start & end lines */
for (line_end = 0; line_end < ta->line_count - 1; line_end++)
if (ta->lines[line_end + 1].b_start > (unsigned)ta->sel_start) {
line_start = line_end;
break;
}
for (; line_end < ta->line_count - 1; line_end++)
if (ta->lines[line_end + 1].b_start > (unsigned)ta->sel_end)
break;
/* Clear selection and redraw */
ta->sel_start = ta->sel_end = -1;
msg.ta = ta;
msg.type = TEXTAREA_MSG_REDRAW_REQUEST;
msg.data.redraw.x0 = ta->border_width;
msg.data.redraw.y0 = ta->border_width;
msg.data.redraw.y0 = max(ta->border_width,
ta->line_height * line_start +
ta->text_y_offset - ta->scroll_y);
msg.data.redraw.x1 = ta->vis_width - ta->border_width -
((ta->bar_y == NULL) ? 0 : SCROLLBAR_WIDTH);
msg.data.redraw.y1 = ta->vis_height - ta->border_width -
((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
msg.data.redraw.y1 = min(ta->vis_height - ta->border_width -
((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH),
ta->line_height * line_end + ta->text_y_offset +
ta->line_height - ta->scroll_y);
ta->callback(ta->data, &msg);