forked from dnkl/foot
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.9 KiB
168 lines
4.9 KiB
#include "commands.h" |
|
|
|
#define LOG_MODULE "commands" |
|
#define LOG_ENABLE_DBG 0 |
|
#include "log.h" |
|
#include "grid.h" |
|
#include "render.h" |
|
#include "selection.h" |
|
#include "terminal.h" |
|
#include "url-mode.h" |
|
#include "util.h" |
|
|
|
void |
|
cmd_scrollback_up(struct terminal *term, int rows) |
|
{ |
|
if (term->grid == &term->alt) |
|
return; |
|
if (urls_mode_is_active(term)) |
|
return; |
|
|
|
if (term->mouse_tracking != MOUSE_NONE) |
|
return; |
|
|
|
rows = min(rows, term->rows); |
|
xassert(term->grid->offset >= 0); |
|
|
|
int new_view = term->grid->view - rows; |
|
while (new_view < 0) |
|
new_view += term->grid->num_rows; |
|
new_view %= term->grid->num_rows; |
|
|
|
xassert(new_view >= 0); |
|
xassert(new_view < term->grid->num_rows); |
|
|
|
/* Avoid scrolling in uninitialized rows */ |
|
while (term->grid->rows[new_view] == NULL) |
|
new_view = (new_view + 1) % term->grid->num_rows; |
|
|
|
if (new_view == term->grid->view) { |
|
/* |
|
* This happens when scrolling up in a newly opened terminal; |
|
* every single line (except those already visible) are |
|
* uninitialized, and the loop above will bring us back to |
|
* where we started. |
|
*/ |
|
return; |
|
} |
|
|
|
/* Don't scroll past scrollback history */ |
|
int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; |
|
if (end >= term->grid->offset) { |
|
/* Not wrapped */ |
|
if (new_view >= term->grid->offset && new_view <= end) |
|
new_view = (end + 1) % term->grid->num_rows; |
|
} else { |
|
if (new_view >= term->grid->offset || new_view <= end) |
|
new_view = (end + 1) % term->grid->num_rows; |
|
} |
|
|
|
while (term->grid->rows[new_view] == NULL) |
|
new_view = (new_view + 1) % term->grid->num_rows; |
|
|
|
#if defined(_DEBUG) |
|
for (int r = 0; r < term->rows; r++) |
|
xassert(term->grid->rows[(new_view + r) % term->grid->num_rows] != NULL); |
|
#endif |
|
|
|
LOG_DBG("scrollback UP: %d -> %d (offset = %d, end = %d, rows = %d)", |
|
term->grid->view, new_view, term->grid->offset, end, term->grid->num_rows); |
|
|
|
if (new_view == term->grid->view) |
|
return; |
|
|
|
int diff = -1; |
|
if (new_view < term->grid->view) |
|
diff = term->grid->view - new_view; |
|
else |
|
diff = (term->grid->num_rows - new_view) + term->grid->view; |
|
|
|
selection_view_up(term, new_view); |
|
term->grid->view = new_view; |
|
|
|
if (diff >= 0 && diff < term->rows) { |
|
term_damage_scroll(term, DAMAGE_SCROLL_REVERSE_IN_VIEW, (struct scroll_region){0, term->rows}, diff); |
|
term_damage_rows_in_view(term, 0, diff - 1); |
|
} else |
|
term_damage_view(term); |
|
|
|
render_refresh_urls(term); |
|
render_refresh(term); |
|
} |
|
|
|
void |
|
cmd_scrollback_down(struct terminal *term, int rows) |
|
{ |
|
if (term->grid == &term->alt) |
|
return; |
|
if (urls_mode_is_active(term)) |
|
return; |
|
|
|
if (term->mouse_tracking != MOUSE_NONE) |
|
return; |
|
|
|
if (term->grid->view == term->grid->offset) |
|
return; |
|
|
|
rows = min(rows, term->rows); |
|
xassert(term->grid->offset >= 0); |
|
|
|
int new_view = (term->grid->view + rows) % term->grid->num_rows; |
|
xassert(new_view >= 0); |
|
xassert(new_view < term->grid->num_rows); |
|
|
|
/* Prevent scrolling in uninitialized rows */ |
|
bool all_initialized = false; |
|
do { |
|
all_initialized = true; |
|
|
|
for (int i = 0; i < term->rows; i++) { |
|
int row_no = (new_view + i) % term->grid->num_rows; |
|
if (term->grid->rows[row_no] == NULL) { |
|
all_initialized = false; |
|
new_view--; |
|
break; |
|
} |
|
} |
|
} while (!all_initialized); |
|
|
|
/* Don't scroll past scrollback history */ |
|
int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; |
|
if (end >= term->grid->offset) { |
|
/* Not wrapped */ |
|
if (new_view >= term->grid->offset && new_view <= end) |
|
new_view = term->grid->offset; |
|
} else { |
|
if (new_view >= term->grid->offset || new_view <= end) |
|
new_view = term->grid->offset; |
|
} |
|
|
|
#if defined(_DEBUG) |
|
for (int r = 0; r < term->rows; r++) |
|
xassert(term->grid->rows[(new_view + r) % term->grid->num_rows] != NULL); |
|
#endif |
|
|
|
LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, end = %d, rows = %d)", |
|
term->grid->view, new_view, term->grid->offset, end, term->grid->num_rows); |
|
|
|
if (new_view == term->grid->view) |
|
return; |
|
|
|
int diff = -1; |
|
if (new_view > term->grid->view) |
|
diff = new_view - term->grid->view; |
|
else |
|
diff = (term->grid->num_rows - term->grid->view) + new_view; |
|
|
|
selection_view_down(term, new_view); |
|
term->grid->view = new_view; |
|
|
|
if (diff >= 0 && diff < term->rows) { |
|
term_damage_scroll(term, DAMAGE_SCROLL_IN_VIEW, (struct scroll_region){0, term->rows}, diff); |
|
term_damage_rows_in_view(term, term->rows - diff, term->rows - 1); |
|
} else |
|
term_damage_view(term); |
|
|
|
render_refresh_urls(term); |
|
render_refresh(term); |
|
}
|
|
|