diff --git a/firmware/scroll_engine.c b/firmware/scroll_engine.c index 200695b5d6..9607c90448 100644 --- a/firmware/scroll_engine.c +++ b/firmware/scroll_engine.c @@ -84,6 +84,18 @@ void lcd_stop_scroll(void) lcd_scroll_info.lines = 0; } +/* returns true if the 'line' in 'lines_vp' would scroll into 'othervp' */ +static bool line_overlaps_viewport(struct viewport *lines_vp, int line, + struct viewport *othervp) +{ + int y = (font_get(lines_vp->font)->height*line) + lines_vp->y; + if (y < othervp->y || y > othervp->y + othervp->height) + return false; + else if ((lines_vp->x + lines_vp->width < othervp->x) || + (othervp->x + othervp->width < lines_vp->x)) + return false; + return true; +} /* Stop scrolling line y in the specified viewport, or all lines if y < 0 */ void lcd_scroll_stop_line(struct viewport* current_vp, int y) { @@ -91,8 +103,11 @@ void lcd_scroll_stop_line(struct viewport* current_vp, int y) while (i < lcd_scroll_info.lines) { - if ((lcd_scroll_info.scroll[i].vp == current_vp) && - ((y < 0) || (lcd_scroll_info.scroll[i].y == y))) + if (((lcd_scroll_info.scroll[i].vp == current_vp) && + ((y < 0) || (lcd_scroll_info.scroll[i].y == y))) || + ((lcd_scroll_info.scroll[i].vp != current_vp) && + line_overlaps_viewport(lcd_scroll_info.scroll[i].vp, + lcd_scroll_info.scroll[i].y, current_vp))) { /* If i is not the last active line in the array, then move the last item to position i */ @@ -102,8 +117,10 @@ void lcd_scroll_stop_line(struct viewport* current_vp, int y) } lcd_scroll_info.lines--; - /* A line can only appear once, so we're done. */ - return ; + /* A line can only appear once, so we're done, + * unless we are clearing the whole viewport */ + if (y >= 0) + return ; } else { @@ -165,8 +182,11 @@ void lcd_remote_scroll_stop_line(struct viewport* current_vp, int y) while (i < lcd_remote_scroll_info.lines) { - if ((lcd_remote_scroll_info.scroll[i].vp == current_vp) && - ((y < 0) || (lcd_remote_scroll_info.scroll[i].y == y))) + if (((lcd_remote_scroll_info.scroll[i].vp == current_vp) && + ((y < 0) || (lcd_remote_scroll_info.scroll[i].y == y))) || + (((lcd_remote_scroll_info.scroll[i].vp != current_vp) && + line_overlaps_viewport(lcd_scroll_info.scroll[i].vp, + lcd_scroll_info.scroll[i].y, current_vp)))) { /* If i is not the last active line in the array, then move the last item to position i */ @@ -176,8 +196,10 @@ void lcd_remote_scroll_stop_line(struct viewport* current_vp, int y) } lcd_remote_scroll_info.lines--; - /* A line can only appear once, so we're done. */ - return ; + /* A line can only appear once, so we're done, + * unless we are clearing the whole viewport */ + if (y >= 0) + return ; } else {