SHL_EXPORT void tsm_screen_tab_left(struct tsm_screen *con, unsigned int num) { unsigned int i, x; int j; if (!con || !num) return; screen_inc_age(con); x = con->cursor_x; for (i = 0; i < num; ++i) { for (j = x - 1; j > 0; --j) { if (con->tab_ruler[j]) break; } if (j <= 0) { x = 0; break; } x = j; } move_cursor(con, x, con->cursor_y); }
SHL_EXPORT void tsm_screen_move_down(struct tsm_screen *con, unsigned int num, bool scroll) { unsigned int diff, size; if (!con || !num) return; screen_inc_age(con); if (con->cursor_y <= con->margin_bottom) size = con->margin_bottom + 1; else size = con->size_y; diff = size - con->cursor_y - 1; if (num > diff) { num -= diff; if (scroll) screen_scroll_up(con, num); move_cursor(con, con->cursor_x, size - 1); } else { move_cursor(con, con->cursor_x, con->cursor_y + num); } }
SHL_EXPORT void tsm_screen_delete_chars(struct tsm_screen *con, unsigned int num) { struct cell *cells; unsigned int max, mv, i; if (!con || !num || !con->size_y || !con->size_x) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; if (con->cursor_x >= con->size_x) con->cursor_x = con->size_x - 1; if (con->cursor_y >= con->size_y) con->cursor_y = con->size_y - 1; max = con->size_x - con->cursor_x; if (num > max) num = max; mv = max - num; cells = con->lines[con->cursor_y]->cells; if (mv) memmove(&cells[con->cursor_x], &cells[con->cursor_x + num], mv * sizeof(*cells)); for (i = 0; i < num; ++i) screen_cell_init(con, &cells[con->cursor_x + mv + i]); }
SHL_EXPORT void tsm_screen_move_up(struct tsm_screen *con, unsigned int num, bool scroll) { unsigned int diff, size; if (!con || !num) return; screen_inc_age(con); if (con->cursor_y >= con->margin_top) size = con->margin_top; else size = 0; diff = con->cursor_y - size; if (num > diff) { num -= diff; if (scroll) screen_scroll_down(con, num); move_cursor(con, con->cursor_x, size); } else { move_cursor(con, con->cursor_x, con->cursor_y - num); } }
SHL_EXPORT void tsm_screen_move_to(struct tsm_screen *con, unsigned int x, unsigned int y) { unsigned int last; if (!con) return; screen_inc_age(con); if (con->flags & TSM_SCREEN_REL_ORIGIN) last = con->margin_bottom; else last = con->size_y - 1; x = to_abs_x(con, x); if (x >= con->size_x) x = con->size_x - 1; y = to_abs_y(con, y); if (y > last) y = last; move_cursor(con, x, y); }
SHL_EXPORT void tsm_screen_reset_flags(struct tsm_screen *con, unsigned int flags) { unsigned int old; struct cell *c; if (!con || !flags) return; screen_inc_age(con); old = con->flags; con->flags &= ~flags; if ((old & TSM_SCREEN_ALTERNATE) && (flags & TSM_SCREEN_ALTERNATE)) { con->age = con->age_cnt; con->lines = con->main_lines; } if ((old & TSM_SCREEN_HIDE_CURSOR) && (flags & TSM_SCREEN_HIDE_CURSOR)) { c = get_cursor_cell(con); c->age = con->age_cnt; } if ((old & TSM_SCREEN_INVERSE) && (flags & TSM_SCREEN_INVERSE)) con->age = con->age_cnt; }
/* clear scrollback buffer */ SHL_EXPORT void tsm_screen_clear_sb(struct tsm_screen *con) { struct line *iter, *tmp; if (!con) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; for (iter = con->sb_first; iter; ) { tmp = iter; iter = iter->next; line_free(tmp); } con->sb_first = NULL; con->sb_last = NULL; con->sb_count = 0; con->sb_pos = NULL; if (con->sel_active) { if (con->sel_start.line) { con->sel_start.line = NULL; con->sel_start.y = SELECTION_TOP; } if (con->sel_end.line) { con->sel_end.line = NULL; con->sel_end.y = SELECTION_TOP; } } }
SHL_EXPORT void tsm_screen_tab_right(struct tsm_screen *con, unsigned int num) { unsigned int i, j, x; if (!con || !num) return; screen_inc_age(con); x = con->cursor_x; for (i = 0; i < num; ++i) { for (j = x + 1; j < con->size_x; ++j) { if (con->tab_ruler[j]) break; } x = j; if (x + 1 >= con->size_x) break; } /* tabs never cause pending new-lines */ if (x >= con->size_x) x = con->size_x - 1; move_cursor(con, x, con->cursor_y); }
SHL_EXPORT void tsm_screen_sb_page_down(struct tsm_screen *con, unsigned int num) { if (!con || !num) return; screen_inc_age(con); tsm_screen_sb_down(con, num * con->size_y); }
SHL_EXPORT void tsm_screen_scroll_down(struct tsm_screen *con, unsigned int num) { if (!con || !num) return; screen_inc_age(con); screen_scroll_down(con, num); }
SHL_EXPORT void tsm_screen_move_line_end(struct tsm_screen *con) { if (!con) return; screen_inc_age(con); move_cursor(con, con->size_x - 1, con->cursor_y); }
SHL_EXPORT void tsm_screen_move_line_home(struct tsm_screen *con) { if (!con) return; screen_inc_age(con); move_cursor(con, 0, con->cursor_y); }
SHL_EXPORT void tsm_screen_erase_screen(struct tsm_screen *con, bool protect) { if (!con) return; screen_inc_age(con); screen_erase_region(con, 0, 0, con->size_x - 1, con->size_y - 1, protect); }
SHL_EXPORT void tsm_screen_erase_screen_to_cursor(struct tsm_screen *con, bool protect) { if (!con) return; screen_inc_age(con); screen_erase_region(con, 0, 0, con->cursor_x, con->cursor_y, protect); }
SHL_EXPORT void tsm_screen_newline(struct tsm_screen *con) { if (!con) return; screen_inc_age(con); tsm_screen_move_down(con, 1, true); tsm_screen_move_line_home(con); }
SHL_EXPORT void tsm_screen_erase_current_line(struct tsm_screen *con, bool protect) { if (!con) return; screen_inc_age(con); screen_erase_region(con, 0, con->cursor_y, con->size_x - 1, con->cursor_y, protect); }
SHL_EXPORT void tsm_screen_sb_reset(struct tsm_screen *con) { if (!con) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; con->sb_pos = NULL; }
SHL_EXPORT void tsm_screen_selection_reset(struct tsm_screen *con) { if (!con) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; con->sel_active = false; }
SHL_EXPORT void tsm_screen_selection_target(struct tsm_screen *con, unsigned int posx, unsigned int posy) { if (!con || !con->sel_active) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; selection_set(con, &con->sel_end, posx, posy); }
SHL_EXPORT void tsm_screen_move_right(struct tsm_screen *con, unsigned int num) { if (!con || !num) return; screen_inc_age(con); if (num > con->size_x) num = con->size_x; if (num + con->cursor_x >= con->size_x) move_cursor(con, con->size_x - 1, con->cursor_y); else move_cursor(con, con->cursor_x + num, con->cursor_y); }
SHL_EXPORT void tsm_screen_selection_start(struct tsm_screen *con, unsigned int posx, unsigned int posy) { if (!con) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; con->sel_active = true; selection_set(con, &con->sel_start, posx, posy); memcpy(&con->sel_end, &con->sel_start, sizeof(con->sel_end)); }
SHL_EXPORT void tsm_screen_erase_cursor(struct tsm_screen *con) { unsigned int x; if (!con) return; screen_inc_age(con); if (con->cursor_x >= con->size_x) x = con->size_x - 1; else x = con->cursor_x; screen_erase_region(con, x, con->cursor_y, x, con->cursor_y, false); }
SHL_EXPORT void tsm_screen_sb_down(struct tsm_screen *con, unsigned int num) { if (!con || !num) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; while (num--) { if (con->sb_pos) con->sb_pos = con->sb_pos->next; else return; } }
SHL_EXPORT void tsm_screen_erase_cursor_to_screen(struct tsm_screen *con, bool protect) { unsigned int x; if (!con) return; screen_inc_age(con); if (con->cursor_x >= con->size_x) x = con->size_x - 1; else x = con->cursor_x; screen_erase_region(con, x, con->cursor_y, con->size_x - 1, con->size_y - 1, protect); }
/* set maximum scrollback buffer size */ SHL_EXPORT void tsm_screen_set_max_sb(struct tsm_screen *con, unsigned int max) { struct line *line; if (!con) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; while (con->sb_count > max) { line = con->sb_first; con->sb_first = line->next; if (line->next) line->next->prev = NULL; else con->sb_last = NULL; con->sb_count--; /* We treat fixed/unfixed position the same here because we * remove lines from the TOP of the scrollback buffer. */ if (con->sb_pos == line) con->sb_pos = con->sb_first; if (con->sel_active) { if (con->sel_start.line == line) { con->sel_start.line = NULL; con->sel_start.y = SELECTION_TOP; } if (con->sel_end.line == line) { con->sel_end.line = NULL; con->sel_end.y = SELECTION_TOP; } } line_free(line); } con->sb_max = max; }
SHL_EXPORT void tsm_screen_move_left(struct tsm_screen *con, unsigned int num) { unsigned int x; if (!con || !num) return; screen_inc_age(con); if (num > con->size_x) num = con->size_x; x = con->cursor_x; if (x >= con->size_x) x = con->size_x - 1; if (num > x) move_cursor(con, 0, con->cursor_y); else move_cursor(con, x - num, con->cursor_y); }
SHL_EXPORT void tsm_screen_delete_lines(struct tsm_screen *con, unsigned int num) { unsigned int i, j, max; if (!con || !num) return; if (con->cursor_y < con->margin_top || con->cursor_y > con->margin_bottom) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; max = con->margin_bottom - con->cursor_y + 1; if (num > max) num = max; struct line *cache[num]; for (i = 0; i < num; ++i) { cache[i] = con->lines[con->cursor_y + i]; for (j = 0; j < con->size_x; ++j) screen_cell_init(con, &cache[i]->cells[j]); } if (num < max) { memmove(&con->lines[con->cursor_y], &con->lines[con->cursor_y + num], (max - num) * sizeof(struct line*)); memcpy(&con->lines[con->cursor_y + (max - num)], cache, num * sizeof(struct line*)); } con->cursor_x = 0; }
SHL_EXPORT void tsm_screen_reset(struct tsm_screen *con) { unsigned int i; if (!con) return; screen_inc_age(con); con->age = con->age_cnt; con->flags = 0; con->margin_top = 0; con->margin_bottom = con->size_y - 1; con->lines = con->main_lines; for (i = 0; i < con->size_x; ++i) { if (i % 8 == 0) con->tab_ruler[i] = true; else con->tab_ruler[i] = false; } }
SHL_EXPORT void tsm_screen_sb_up(struct tsm_screen *con, unsigned int num) { if (!con || !num) return; screen_inc_age(con); /* TODO: more sophisticated ageing */ con->age = con->age_cnt; while (num--) { if (con->sb_pos) { if (!con->sb_pos->prev) return; con->sb_pos = con->sb_pos->prev; } else if (!con->sb_last) { return; } else { con->sb_pos = con->sb_last; } } }
SHL_EXPORT void tsm_screen_write(struct tsm_screen *con, tsm_symbol_t ch, const struct tsm_screen_attr *attr) { unsigned int last, len; if (!con) return; len = tsm_symbol_get_width(con->sym_table, ch); if (!len) return; screen_inc_age(con); if (con->cursor_y <= con->margin_bottom || con->cursor_y >= con->size_y) last = con->margin_bottom; else last = con->size_y - 1; if (con->cursor_x >= con->size_x) { if (con->flags & TSM_SCREEN_AUTO_WRAP) move_cursor(con, 0, con->cursor_y + 1); else move_cursor(con, con->size_x - 1, con->cursor_y); } if (con->cursor_y > last) { move_cursor(con, con->cursor_x, last); screen_scroll_up(con, 1); } screen_write(con, con->cursor_x, con->cursor_y, ch, len, attr); move_cursor(con, con->cursor_x + len, con->cursor_y); }