summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/textarea.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 2ba1c53cc..15d35e1e5 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -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);