new resize/backlog implementation. Closes T2461
idea: store full lines in the backlog. No need to change them on resize
This commit is contained in:
parent
4378f87162
commit
34592ab5b3
|
@ -139,12 +139,12 @@ _draw_line(const Termpty *ty, unsigned int *pixels,
|
|||
Eina_Bool
|
||||
_is_top_bottom_reached(Miniview *mv)
|
||||
{
|
||||
Termpty *ty;
|
||||
int history_len;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(mv, EINA_FALSE);
|
||||
ty = termio_pty_get(mv->termio);
|
||||
history_len = ty->backscroll_num;
|
||||
|
||||
/* TODO: RESIZE */
|
||||
history_len = 42; //termpty_backscroll_len_get(ty);
|
||||
|
||||
if (( (- mv->img_hist) > (int)(mv->img_h - mv->rows - (mv->rows / 2))) &&
|
||||
( (- mv->img_hist) < (int)(history_len + (mv->rows / 2))))
|
||||
|
@ -522,7 +522,8 @@ _deferred_renderer(void *data)
|
|||
evas_object_geometry_get(mv->termio, &ox, &oy, &ow, &oh);
|
||||
if ((ow == 0) || (oh == 0)) return EINA_TRUE;
|
||||
|
||||
history_len = ty->backscroll_num;
|
||||
/* TODO: RESIZE */
|
||||
history_len = 42; //termpty_backscroll_len_get(ty);
|
||||
|
||||
evas_object_image_size_set(mv->img, mv->cols, mv->img_h);
|
||||
ow = mv->cols;
|
||||
|
|
|
@ -133,8 +133,6 @@ termio_scroll(Evas_Object *obj, int direction, int start_y, int end_y)
|
|||
if (mv) miniview_position_offset(mv, direction, EINA_FALSE);
|
||||
// adjust scroll position for added scrollback
|
||||
sd->scroll -= direction;
|
||||
if (sd->scroll > sd->pty->backscroll_num)
|
||||
sd->scroll = sd->pty->backscroll_num;
|
||||
}
|
||||
ty = sd->pty;
|
||||
if (ty->selection.is_active)
|
||||
|
@ -347,15 +345,8 @@ termio_scroll_delta(Evas_Object *obj, int delta, int by_page)
|
|||
delta *= by;
|
||||
}
|
||||
sd->scroll += delta;
|
||||
if (delta > 0)
|
||||
{
|
||||
if (sd->scroll > sd->pty->backscroll_num)
|
||||
sd->scroll = sd->pty->backscroll_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sd->scroll < 0) sd->scroll = 0;
|
||||
}
|
||||
if (delta <= 0 && sd->scroll < 0)
|
||||
sd->scroll = 0;
|
||||
_smart_update_queue(obj, sd);
|
||||
miniview_position_offset(term_miniview_get(sd->term), -delta, EINA_TRUE);
|
||||
}
|
||||
|
@ -2050,6 +2041,7 @@ termio_selection_get(Evas_Object *obj, int c1x, int c1y, int c2x, int c2y,
|
|||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL);
|
||||
termpty_cellcomp_freeze(sd->pty);
|
||||
/* TODO: RESIZE use/save the reference point */
|
||||
for (y = c1y; y <= c2y; y++)
|
||||
{
|
||||
Termcell *cells;
|
||||
|
@ -4127,8 +4119,6 @@ _mouse_selection_scroll(void *data)
|
|||
if (cy == 0)
|
||||
cy = -1;
|
||||
sd->scroll -= cy;
|
||||
if (sd->scroll > sd->pty->backscroll_num)
|
||||
sd->scroll = sd->pty->backscroll_num;
|
||||
sd->pty->selection.end.y = -sd->scroll;
|
||||
_smart_update_queue(data, sd);
|
||||
}
|
||||
|
@ -4324,9 +4314,8 @@ _smart_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNU
|
|||
else
|
||||
{
|
||||
sd->scroll -= (ev->z * 4);
|
||||
if (sd->scroll > sd->pty->backscroll_num)
|
||||
sd->scroll = sd->pty->backscroll_num;
|
||||
else if (sd->scroll < 0) sd->scroll = 0;
|
||||
if (sd->scroll < 0)
|
||||
sd->scroll = 0;
|
||||
_smart_update_queue(data, sd);
|
||||
miniview_position_offset(term_miniview_get(sd->term),
|
||||
ev->z * 4, EINA_TRUE);
|
||||
|
@ -4520,6 +4509,7 @@ _smart_apply(Evas_Object *obj)
|
|||
}
|
||||
inv = sd->pty->termstate.reverse;
|
||||
termpty_cellcomp_freeze(sd->pty);
|
||||
termpty_backscroll_adjust(sd->pty, &sd->scroll);
|
||||
for (y = 0; y < sd->grid.h; y++)
|
||||
{
|
||||
Termcell *cells;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#if defined (__sun) || defined (__sun__)
|
||||
# include <stropts.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
/* specific log domain to help debug only terminal code parser */
|
||||
int _termpty_log_dom = -1;
|
||||
|
@ -298,7 +299,7 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd,
|
|||
if (!ty) return NULL;
|
||||
ty->w = w;
|
||||
ty->h = h;
|
||||
ty->backmax = backscroll;
|
||||
ty->backsize = backscroll;
|
||||
|
||||
termpty_reset_state(ty);
|
||||
|
||||
|
@ -567,16 +568,9 @@ termpty_free(Termpty *ty)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ty->backmax; i++)
|
||||
{
|
||||
if (ty->back[i])
|
||||
{
|
||||
termpty_save_free(ty->back[i]);
|
||||
ty->back[i] = NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
termpty_save_free(&ty->back[i]);
|
||||
free(ty->back);
|
||||
ty->back = NULL;
|
||||
}
|
||||
free(ty->screen);
|
||||
free(ty->screen2);
|
||||
|
@ -596,6 +590,24 @@ termpty_cellcomp_thaw(Termpty *ty EINA_UNUSED)
|
|||
termpty_save_thaw();
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
termpty_line_is_empty(const Termcell *cells, ssize_t nb_cells)
|
||||
{
|
||||
ssize_t len = nb_cells;
|
||||
|
||||
for (len = nb_cells - 1; len >= 0; len--)
|
||||
{
|
||||
const Termcell *cell = cells + len;
|
||||
|
||||
if ((cell->codepoint != 0) &&
|
||||
(cell->att.bg != COL_INVIS))
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
termpty_line_length(const Termcell *cells, ssize_t nb_cells)
|
||||
{
|
||||
|
@ -613,6 +625,48 @@ termpty_line_length(const Termcell *cells, ssize_t nb_cells)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define BACKLOG_ROW_GET(Ty, Y) \
|
||||
(&Ty->back[(Ty->backsize + ty->backpos - (Y)) % Ty->backsize])
|
||||
|
||||
void
|
||||
termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
|
||||
{
|
||||
Termsave *ts;
|
||||
ssize_t w;
|
||||
|
||||
if (ty->backsize <= 0)
|
||||
return;
|
||||
assert(ty->back);
|
||||
|
||||
termpty_save_freeze();
|
||||
|
||||
w = termpty_line_length(cells, w_max);
|
||||
if (ty->backsize >= 1)
|
||||
{
|
||||
ts = BACKLOG_ROW_GET(ty, 0);
|
||||
if (!ts->cells)
|
||||
goto add_new_ts;
|
||||
/* TODO: RESIZE uncompress ? */
|
||||
if (ts->w && ts->cells[ts->w - 1].att.autowrapped)
|
||||
{
|
||||
termpty_save_expand(ts, cells, w);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
add_new_ts:
|
||||
ts = BACKLOG_ROW_GET(ty, -1);
|
||||
ts = termpty_save_new(ts, w);
|
||||
if (!ts)
|
||||
return;
|
||||
termpty_cell_copy(ty, cells, ts->cells, w);
|
||||
ty->backpos++;
|
||||
if (ty->backpos >= ty->backsize)
|
||||
ty->backpos = 0;
|
||||
termpty_save_thaw();
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
termpty_row_length(Termpty *ty, int y)
|
||||
{
|
||||
|
@ -629,38 +683,114 @@ termpty_row_length(Termpty *ty, int y)
|
|||
cells = &(TERMPTY_SCREEN(ty, 0, y));
|
||||
return termpty_line_length(cells, ty->w);
|
||||
}
|
||||
if ((y < -ty->backmax) || !ty->back)
|
||||
if ((y < -ty->backsize) || !ty->back)
|
||||
{
|
||||
ERR("invalid row given");
|
||||
return 0;
|
||||
}
|
||||
ts = ty->back[(ty->backmax + ty->backpos + y) % ty->backmax];
|
||||
if (!ts) return 0;
|
||||
ts = BACKLOG_ROW_GET(ty, y);
|
||||
|
||||
return ts->comp ? ((Termsavecomp*)ts)->wout : ts->w;
|
||||
return ts->cells ? ts->w : 0;
|
||||
}
|
||||
|
||||
/* TODO: RESIZE reference point */
|
||||
|
||||
void
|
||||
termpty_backscroll_adjust(Termpty *ty, int *scroll)
|
||||
{
|
||||
Termsave *ts;
|
||||
int y;
|
||||
int screen_y;
|
||||
|
||||
if (!ty->backsize || *scroll <= 0)
|
||||
{
|
||||
*scroll = 0;
|
||||
return;
|
||||
}
|
||||
ERR("ty->backsize:%d ty->backpos:%d *scroll:%d",
|
||||
ty->backsize, ty->backpos, *scroll);
|
||||
/* TODO: RESIZE have a reference point? */
|
||||
y = ty->backsize;
|
||||
do
|
||||
{
|
||||
y--;
|
||||
ts = BACKLOG_ROW_GET(ty, y);
|
||||
}
|
||||
while (!ts->cells);
|
||||
ERR("y:%d", y);
|
||||
if (*scroll <= y)
|
||||
return;
|
||||
screen_y = 0;
|
||||
while (y >= 0)
|
||||
{
|
||||
int nb_lines;
|
||||
|
||||
ts = BACKLOG_ROW_GET(ty, y);
|
||||
assert(ts != NULL);
|
||||
|
||||
nb_lines = (ts->w + ty->w) / ty->w;
|
||||
ERR("[%d] ts->w:%d ty->w:%d, nb_lines:%d",
|
||||
y, ts->w, ty->w, nb_lines);
|
||||
screen_y += nb_lines;
|
||||
y--;
|
||||
}
|
||||
|
||||
ERR("screen_y:%d", screen_y);
|
||||
*scroll = screen_y;
|
||||
}
|
||||
|
||||
|
||||
Termcell *
|
||||
termpty_cellrow_get(Termpty *ty, int y, int *wret)
|
||||
termpty_cellrow_get(Termpty *ty, int y_requested, int *wret)
|
||||
{
|
||||
Termsave *ts, **tssrc;
|
||||
int screen_y = 0;
|
||||
int backlog_y = 0;
|
||||
|
||||
if (y >= 0)
|
||||
//ERR("y_requested:%d", y_requested);
|
||||
if (y_requested >= 0)
|
||||
{
|
||||
if (y >= ty->h) return NULL;
|
||||
if (y_requested >= ty->h)
|
||||
return NULL;
|
||||
*wret = ty->w;
|
||||
/* fprintf(stderr, "getting: %i (%i, %i)\n", y, ty->circular_offset, ty->h); */
|
||||
return &(TERMPTY_SCREEN(ty, 0, y));
|
||||
return &(TERMPTY_SCREEN(ty, 0, y_requested));
|
||||
}
|
||||
if ((y < -ty->backmax) || !ty->back) return NULL;
|
||||
tssrc = &(ty->back[(ty->backmax + ty->backpos + y) % ty->backmax]);
|
||||
ts = termpty_save_extract(*tssrc);
|
||||
if (!ts) return NULL;
|
||||
*tssrc = ts;
|
||||
*wret = ts->w;
|
||||
return ts->cell;
|
||||
if (!ty->back)
|
||||
return NULL;
|
||||
|
||||
y_requested = -y_requested;
|
||||
while (backlog_y <= ty->backsize)
|
||||
{
|
||||
Termsave *ts;
|
||||
int nb_lines;
|
||||
|
||||
ts = BACKLOG_ROW_GET(ty, backlog_y);
|
||||
if (!ts->cells)
|
||||
{
|
||||
//ERR("went too far: y_requested:%d screen_y:%d backlog_y:%d",
|
||||
// y_requested, screen_y, backlog_y);
|
||||
return NULL;
|
||||
}
|
||||
nb_lines = (ts->w + ty->w) / ty->w;
|
||||
|
||||
/* TODO: uncompress */
|
||||
/* TODO: optimize */
|
||||
|
||||
//ERR("y_requested:%d screen_y:%d nb_lines:%d backlog_y:%d",
|
||||
// y_requested, screen_y, nb_lines, backlog_y);
|
||||
if (screen_y + nb_lines >= y_requested)
|
||||
{
|
||||
int delta = screen_y + nb_lines - y_requested;
|
||||
*wret = ts->w - delta * ty->w;
|
||||
if (*wret > ts->w)
|
||||
*wret = ts->w;
|
||||
return &ts->cells[delta * ty->w];
|
||||
}
|
||||
screen_y += nb_lines;
|
||||
backlog_y++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
termpty_write(Termpty *ty, const char *input, int len)
|
||||
{
|
||||
|
@ -670,170 +800,113 @@ termpty_write(Termpty *ty, const char *input, int len)
|
|||
ty->fd, strerror(errno));
|
||||
}
|
||||
|
||||
static int
|
||||
termpty_line_find_top(Termpty *ty, int y_end, int *top)
|
||||
struct screen_info
|
||||
{
|
||||
int y_start = y_end;
|
||||
Termcell *screen;
|
||||
int w;
|
||||
int h;
|
||||
int x;
|
||||
int y;
|
||||
int cy;
|
||||
int cx;
|
||||
int circular_offset;
|
||||
};
|
||||
|
||||
while (y_start > 0)
|
||||
#define SCREEN_INFO_GET_CELLS(Tsi, X, Y) \
|
||||
Tsi->screen[X + (((Y + Tsi->circular_offset) % Tsi->h) * Tsi->w)]
|
||||
|
||||
static void
|
||||
_check_screen_info(Termpty *ty, struct screen_info *si)
|
||||
{
|
||||
if (si->y >= si->h)
|
||||
{
|
||||
if (TERMPTY_SCREEN(ty, ty->w - 1, y_start - 1).att.autowrapped)
|
||||
y_start--;
|
||||
else
|
||||
{
|
||||
*top = y_start;
|
||||
return 0;
|
||||
}
|
||||
Termcell *cells = &SCREEN_INFO_GET_CELLS(si, 0, 0);
|
||||
|
||||
ERR("adjusting");
|
||||
|
||||
si->y--;
|
||||
termpty_text_save_top(ty, cells, si->w);
|
||||
termpty_cells_clear(ty, cells, si->w);
|
||||
|
||||
si->circular_offset++;
|
||||
if (si->circular_offset >= si->h)
|
||||
si->circular_offset = 0;
|
||||
|
||||
si->cy--;
|
||||
}
|
||||
while (-y_start < ty->backscroll_num)
|
||||
{
|
||||
Termsave *ts = ty->back[(y_start + ty->backpos - 1 +
|
||||
ty->backmax) % ty->backmax];
|
||||
if (ts)
|
||||
{
|
||||
ts = termpty_save_extract(ts);
|
||||
}
|
||||
if (!ts)
|
||||
return -1;
|
||||
ty->back[(y_start + ty->backpos - 1 + ty->backmax) % ty->backmax] = ts;
|
||||
if (ts->cell[ts->w - 1].att.autowrapped)
|
||||
y_start--;
|
||||
else
|
||||
{
|
||||
*top = y_start;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*top = y_start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
termpty_line_rewrap(Termpty *ty, int y_start, int y_end,
|
||||
Termcell *new_screen, Termsave **new_back,
|
||||
int new_w, int new_y_end, int *new_y_startp,
|
||||
int *new_cyp)
|
||||
static void
|
||||
_termpty_line_rewrap(Termpty *ty, Termcell *cells, int len,
|
||||
struct screen_info *si,
|
||||
Eina_Bool set_cursor)
|
||||
{
|
||||
/* variables prefixed by new_ are about the resized term being built up */
|
||||
int x, y, new_x, new_y, new_y_start;
|
||||
int len, len_last, len_remaining, copy_width, new_ts_width;
|
||||
Termsave *ts, *new_ts;
|
||||
Termcell *line, *new_line = NULL;
|
||||
int autowrapped = cells[len-1].att.autowrapped;
|
||||
|
||||
if (y_end >= 0)
|
||||
ERR("si->x:%d si->y:%d si->cx:%d si->cy:%d",
|
||||
si->x, si->y, si->cx, si->cy);
|
||||
if (len == 0)
|
||||
{
|
||||
len_last = termpty_line_length(&TERMPTY_SCREEN(ty, 0, y_end), ty->w);
|
||||
if (set_cursor)
|
||||
{
|
||||
si->cy = si->y;
|
||||
si->cx = 0;
|
||||
}
|
||||
si->y++;
|
||||
si->x = 0;
|
||||
_check_screen_info(ty, si);
|
||||
return;
|
||||
}
|
||||
else
|
||||
while (len > 0)
|
||||
{
|
||||
ts = termpty_save_extract(ty->back[(y_end + ty->backpos +
|
||||
ty->backmax) % ty->backmax]);
|
||||
if (!ts)
|
||||
return -1;
|
||||
ty->back[(y_end + ty->backpos + ty->backmax) % ty->backmax] = ts;
|
||||
len_last = ts->w;
|
||||
}
|
||||
len_remaining = len_last + (y_end - y_start) * ty->w;
|
||||
new_y_start = new_y_end;
|
||||
if (len_remaining)
|
||||
{
|
||||
new_y_start -= (len_remaining + new_w - 1) / new_w - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_y_start < 0)
|
||||
new_back[new_y_start + ty->backmax] = termpty_save_new(0);
|
||||
*new_y_startp = new_y_start;
|
||||
return 0;
|
||||
}
|
||||
if (-new_y_start > ty->backmax)
|
||||
{
|
||||
y_start += ((-new_y_start - ty->backmax) * new_w) / ty->w;
|
||||
x = ((-new_y_start - ty->backmax) * new_w) % ty->w;
|
||||
len_remaining -= (-new_y_start - ty->backmax) * new_w;
|
||||
new_y_start = -ty->backmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0;
|
||||
}
|
||||
y = y_start;
|
||||
new_x = 0;
|
||||
new_y = new_y_start;
|
||||
int copy_width = MIN(len, si->w - si->x);
|
||||
|
||||
while (y <= y_end)
|
||||
{
|
||||
if (y >= 0)
|
||||
ERR("len:%d copy_width:%d", len, copy_width);
|
||||
termpty_cell_copy(ty,
|
||||
/*src*/ cells,
|
||||
/*dst*/&SCREEN_INFO_GET_CELLS(si, si->x, si->y),
|
||||
copy_width);
|
||||
if (set_cursor)
|
||||
{
|
||||
line = &TERMPTY_SCREEN(ty, 0, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
ts = termpty_save_extract(ty->back[(y + ty->backpos +
|
||||
ty->backmax) % ty->backmax]);
|
||||
if (!ts)
|
||||
return -1;
|
||||
ty->back[(y + ty->backpos + ty->backmax) % ty->backmax] = ts;
|
||||
line = ts->cell;
|
||||
}
|
||||
if (y == y_end)
|
||||
len = len_last;
|
||||
else
|
||||
len = ty->w;
|
||||
line[len - 1].att.autowrapped = 0;
|
||||
while (x < len)
|
||||
{
|
||||
copy_width = MIN(len - x, new_w - new_x);
|
||||
if (new_x == 0)
|
||||
if (ty->cursor_state.cx <= copy_width)
|
||||
{
|
||||
if (new_y >= 0)
|
||||
{
|
||||
new_line = new_screen + (new_y * new_w);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_ts_width = MIN(len_remaining, new_w);
|
||||
new_ts = termpty_save_new(new_ts_width);
|
||||
if (!new_ts)
|
||||
return -1;
|
||||
new_line = new_ts->cell;
|
||||
new_back[new_y + ty->backmax] = new_ts;
|
||||
}
|
||||
si->cx = ty->cursor_state.cx;
|
||||
si->cy = si->y;
|
||||
}
|
||||
if (y == ty->cursor_state.cy)
|
||||
else
|
||||
{
|
||||
*new_cyp = new_y_start;
|
||||
}
|
||||
if (new_line)
|
||||
{
|
||||
termpty_cell_copy(ty, line + x, new_line + new_x, copy_width);
|
||||
x += copy_width;
|
||||
new_x += copy_width;
|
||||
len_remaining -= copy_width;
|
||||
if ((new_x == new_w) && (new_y != new_y_end))
|
||||
{
|
||||
new_line[new_x - 1].att.autowrapped = 1;
|
||||
new_x = 0;
|
||||
new_y++;
|
||||
}
|
||||
ty->cursor_state.cx -= copy_width;
|
||||
}
|
||||
}
|
||||
x = 0;
|
||||
y++;
|
||||
len -= copy_width;
|
||||
si->x += copy_width;
|
||||
ERR("si->x:%d si->w:%d", si->x, si->w);
|
||||
if (si->x >= si->w)
|
||||
{
|
||||
si->y++;
|
||||
si->x = 0;
|
||||
}
|
||||
_check_screen_info(ty, si);
|
||||
}
|
||||
ERR("autowrapped:%d", autowrapped);
|
||||
if (!autowrapped)
|
||||
{
|
||||
si->y++;
|
||||
si->x = 0;
|
||||
_check_screen_info(ty, si);
|
||||
}
|
||||
*new_y_startp = new_y_start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
termpty_resize(Termpty *ty, int new_w, int new_h)
|
||||
{
|
||||
Termcell *new_screen = NULL;
|
||||
Termsave **new_back = NULL;
|
||||
int y_start = 0, y_end = 0, new_y_start = 0, new_y_end,
|
||||
new_cy = ty->cursor_state.cy;
|
||||
int i, altbuf = 0;
|
||||
int old_y = 0,
|
||||
old_w = ty->w,
|
||||
old_h = ty->h,
|
||||
effective_old_h;
|
||||
int altbuf = 0;
|
||||
struct screen_info new_si = {.screen = NULL};
|
||||
|
||||
if ((ty->w == new_w) && (ty->h == new_h)) return;
|
||||
if ((new_w == new_h) && (new_w == 1)) return; // FIXME: something weird is
|
||||
|
@ -854,47 +927,50 @@ termpty_resize(Termpty *ty, int new_w, int new_h)
|
|||
ty->screen2 = calloc(1, sizeof(Termcell) * new_w * new_h);
|
||||
if (!ty->screen2)
|
||||
goto bad;
|
||||
new_back = calloc(sizeof(Termsave *), ty->backmax);
|
||||
|
||||
y_end = ty->cursor_state.cy;
|
||||
new_y_end = new_h - 1;
|
||||
/* For each "full line" in old buffers, rewrap.
|
||||
* From most recent to oldest */
|
||||
while ((y_end >= -ty->backscroll_num) && (new_y_end >= -ty->backmax))
|
||||
new_si.screen = new_screen;
|
||||
new_si.w = new_w;
|
||||
new_si.h = new_h;
|
||||
|
||||
/* compute the effective height on the old screen */
|
||||
effective_old_h = old_h;
|
||||
for (old_y = old_h -1; old_y >= 0; old_y--)
|
||||
{
|
||||
if (termpty_line_find_top(ty, y_end, &y_start) < 0)
|
||||
goto bad;
|
||||
if (termpty_line_rewrap(ty, y_start, y_end,
|
||||
new_screen, new_back,
|
||||
new_w, new_y_end,
|
||||
&new_y_start, &new_cy) < 0)
|
||||
goto bad;
|
||||
Termcell *cells = &TERMPTY_SCREEN(ty, 0, old_y);
|
||||
if (!termpty_line_is_empty(cells, old_w))
|
||||
{
|
||||
effective_old_h = old_y + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
y_end = y_start - 1;
|
||||
new_y_end = new_y_start - 1;
|
||||
for (old_y = 0; old_y < effective_old_h; old_y++)
|
||||
{
|
||||
/* for each line in the old screen, append it to the new screen */
|
||||
Termcell *cells = &TERMPTY_SCREEN(ty, 0, old_y);
|
||||
int len;
|
||||
|
||||
len = termpty_line_length(cells, old_w);
|
||||
ERR("[%d] len:%d", old_y, len);
|
||||
_termpty_line_rewrap(ty, cells, len, &new_si,
|
||||
old_y == ty->cursor_state.cy);
|
||||
}
|
||||
|
||||
free(ty->screen);
|
||||
ty->screen = new_screen;
|
||||
for (i = 1; i <= ty->backscroll_num; i++)
|
||||
termpty_save_free(ty->back[(ty->backpos - i + ty->backmax) % ty->backmax]);
|
||||
free(ty->back);
|
||||
ty->back = new_back;
|
||||
|
||||
ty->cursor_state.cy = (new_si.cy >= 0) ? new_si.cy : 0;
|
||||
ty->cursor_state.cx = (new_si.cx >= 0) ? new_si.cx : 0;
|
||||
ty->circular_offset = new_si.circular_offset;
|
||||
|
||||
ty->w = new_w;
|
||||
ty->h = new_h;
|
||||
ty->circular_offset = MAX(new_y_start, 0);
|
||||
ty->backpos = 0;
|
||||
ty->backscroll_num = MAX(-new_y_start, 0);
|
||||
ty->termstate.had_cr = 0;
|
||||
|
||||
ty->cursor_state.cy = (new_cy + new_h - ty->circular_offset) % new_h;
|
||||
ty->termstate.wrapnext = 0;
|
||||
|
||||
if (altbuf)
|
||||
termpty_screen_swap(ty);
|
||||
|
||||
ty->termstate.wrapnext = 0;
|
||||
|
||||
_limit_coord(ty);
|
||||
|
||||
_pty_size(ty);
|
||||
|
@ -905,8 +981,6 @@ termpty_resize(Termpty *ty, int new_w, int new_h)
|
|||
bad:
|
||||
termpty_save_thaw();
|
||||
free(new_screen);
|
||||
free(new_back);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -914,25 +988,24 @@ termpty_backscroll_set(Termpty *ty, int size)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (ty->backmax == size) return;
|
||||
|
||||
if (ty->backsize == size)
|
||||
return;
|
||||
|
||||
/* TODO: RESIZE: handle that case better: changing backscroll size */
|
||||
termpty_save_freeze();
|
||||
|
||||
if (ty->back)
|
||||
{
|
||||
for (i = 0; i < ty->backmax; i++)
|
||||
{
|
||||
if (ty->back[i]) termpty_save_free(ty->back[i]);
|
||||
}
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
termpty_save_free(&ty->back[i]);
|
||||
free(ty->back);
|
||||
}
|
||||
if (size > 0)
|
||||
ty->back = calloc(1, sizeof(Termsave *) * size);
|
||||
ty->back = calloc(1, sizeof(Termsave) * size);
|
||||
else
|
||||
ty->back = NULL;
|
||||
ty->backscroll_num = 0;
|
||||
ty->backpos = 0;
|
||||
ty->backmax = size;
|
||||
ty->backsize = size;
|
||||
termpty_save_thaw();
|
||||
}
|
||||
|
||||
|
@ -1089,7 +1162,7 @@ void
|
|||
termpty_cell_copy(Termpty *ty, Termcell *src, Termcell *dst, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
_handle_block_codepoint_overwrite(ty, dst[i].codepoint, src[i].codepoint);
|
||||
|
|
|
@ -99,7 +99,7 @@ struct _Termpty
|
|||
} prop;
|
||||
const char *cur_cmd;
|
||||
Termcell *screen, *screen2;
|
||||
Termsave **back;
|
||||
Termsave *back;
|
||||
unsigned char oldbuf[4];
|
||||
Eina_Unicode *buf;
|
||||
size_t buflen;
|
||||
|
@ -107,8 +107,7 @@ struct _Termpty
|
|||
int fd, slavefd;
|
||||
int circular_offset;
|
||||
int circular_offset2;
|
||||
int backmax, backpos;
|
||||
int backscroll_num;
|
||||
int backsize, backpos;
|
||||
struct {
|
||||
int curid;
|
||||
Eina_Hash *blocks;
|
||||
|
@ -178,9 +177,11 @@ struct _Termsave
|
|||
unsigned int comp : 1;
|
||||
unsigned int z : 1;
|
||||
unsigned int w : 22;
|
||||
Termcell cell[1];
|
||||
/* TODO: union ? */
|
||||
Termcell *cells;
|
||||
};
|
||||
|
||||
/* TODO: RESIZE rewrite Termsavecomp */
|
||||
struct _Termsavecomp
|
||||
{
|
||||
unsigned int gen : 8;
|
||||
|
@ -232,8 +233,9 @@ void termpty_cellcomp_thaw(Termpty *ty);
|
|||
Termcell *termpty_cellrow_get(Termpty *ty, int y, int *wret);
|
||||
ssize_t termpty_row_length(Termpty *ty, int y);
|
||||
void termpty_write(Termpty *ty, const char *input, int len);
|
||||
void termpty_resize(Termpty *ty, int w, int h);
|
||||
void termpty_resize(Termpty *ty, int new_w, int new_h);
|
||||
void termpty_backscroll_set(Termpty *ty, int size);
|
||||
void termpty_backscroll_adjust(Termpty *ty, int *scroll);
|
||||
|
||||
pid_t termpty_pid_get(const Termpty *ty);
|
||||
void termpty_block_free(Termblock *tb);
|
||||
|
|
|
@ -32,34 +32,6 @@ termpty_cells_clear(Termpty *ty, Termcell *cells, int count)
|
|||
termpty_cell_fill(ty, &src, cells, count);
|
||||
}
|
||||
|
||||
void
|
||||
termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
|
||||
{
|
||||
Termsave *ts;
|
||||
ssize_t w;
|
||||
|
||||
if (ty->backmax <= 0) return;
|
||||
|
||||
termpty_save_freeze();
|
||||
w = termpty_line_length(cells, w_max);
|
||||
ts = termpty_save_new(w);
|
||||
if (!ts)
|
||||
return;
|
||||
termpty_cell_copy(ty, cells, ts->cell, w);
|
||||
if (!ty->back) ty->back = calloc(1, sizeof(Termsave *) * ty->backmax);
|
||||
if (ty->back[ty->backpos])
|
||||
{
|
||||
termpty_save_free(ty->back[ty->backpos]);
|
||||
ty->back[ty->backpos] = NULL;
|
||||
}
|
||||
ty->back[ty->backpos] = ts;
|
||||
ty->backpos++;
|
||||
if (ty->backpos >= ty->backmax) ty->backpos = 0;
|
||||
ty->backscroll_num++;
|
||||
if (ty->backscroll_num >= ty->backmax) ty->backscroll_num = ty->backmax;
|
||||
termpty_save_thaw();
|
||||
}
|
||||
|
||||
void
|
||||
termpty_text_scroll(Termpty *ty, Eina_Bool clear)
|
||||
{
|
||||
|
@ -377,6 +349,8 @@ termpty_reset_att(Termatt *att)
|
|||
void
|
||||
termpty_reset_state(Termpty *ty)
|
||||
{
|
||||
int backsize;
|
||||
|
||||
ty->cursor_state.cx = 0;
|
||||
ty->cursor_state.cy = 0;
|
||||
ty->termstate.scroll_y1 = 0;
|
||||
|
@ -411,17 +385,15 @@ termpty_reset_state(Termpty *ty)
|
|||
if (ty->back)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ty->backmax; i++)
|
||||
{
|
||||
if (ty->back[i]) termpty_save_free(ty->back[i]);
|
||||
}
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
termpty_save_free(&ty->back[i]);
|
||||
free(ty->back);
|
||||
ty->back = NULL;
|
||||
}
|
||||
ty->backscroll_num = 0;
|
||||
ty->backpos = 0;
|
||||
if (ty->backmax)
|
||||
ty->back = calloc(1, sizeof(Termsave *) * ty->backmax);
|
||||
backsize = ty->backsize;
|
||||
ty->backsize = 0;
|
||||
termpty_backscroll_set(ty, backsize);
|
||||
termpty_save_thaw();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,13 @@ struct _Alloc
|
|||
unsigned char __pad;
|
||||
};
|
||||
|
||||
#if 0
|
||||
static uint64_t _allocated = 0;
|
||||
#endif
|
||||
static unsigned char cur_gen = 0;
|
||||
static Alloc *alloc[MEM_BLOCKS] = { 0 };
|
||||
|
||||
#if 0
|
||||
static int
|
||||
roundup_block_size(int sz)
|
||||
{
|
||||
|
@ -122,21 +125,25 @@ _alloc_new(int size, unsigned char gen)
|
|||
ptr += sizeof(Alloc);
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *
|
||||
_ts_new(int size)
|
||||
{
|
||||
void *ptr;
|
||||
/* TODO: RESIZE rewrite that stuff */
|
||||
//void *ptr;
|
||||
|
||||
if (!size) return NULL;
|
||||
ptr = _alloc_new(size, cur_gen);
|
||||
//ptr = _alloc_new(size, cur_gen);
|
||||
|
||||
return ptr;
|
||||
return calloc(1, size);
|
||||
}
|
||||
|
||||
static void
|
||||
_ts_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
#if 0
|
||||
Alloc *al;
|
||||
unsigned int sz;
|
||||
Termsavecomp *ts = ptr;
|
||||
|
@ -165,6 +172,7 @@ _ts_free(void *ptr)
|
|||
#else
|
||||
munmap(al, al->size);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -210,12 +218,15 @@ static Eina_List *ptys = NULL;
|
|||
static Ecore_Idler *idler = NULL;
|
||||
static Ecore_Timer *timer = NULL;
|
||||
|
||||
#if 0
|
||||
static Termsave *
|
||||
_save_comp(Termsave *ts)
|
||||
{
|
||||
Termsave *ts2;
|
||||
Termsavecomp *tsc;
|
||||
|
||||
ERR("save comp");
|
||||
|
||||
// already compacted
|
||||
if (ts->comp) return ts;
|
||||
// make new allocation for new generation
|
||||
|
@ -226,7 +237,7 @@ _save_comp(Termsave *ts)
|
|||
char *buf;
|
||||
|
||||
buf = alloca(LZ4_compressBound(ts->w * sizeof(Termcell)));
|
||||
bytes = LZ4_compress((char *)(&(ts->cell[0])), buf,
|
||||
bytes = LZ4_compress((char *)(&(ts->cells[0])), buf,
|
||||
ts->w * sizeof(Termcell));
|
||||
tsc = _ts_new(sizeof(Termsavecomp) + bytes);
|
||||
if (!tsc)
|
||||
|
@ -262,6 +273,7 @@ done:
|
|||
ts_compfreeze--;
|
||||
return ts2;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_walk_pty(Termpty *ty)
|
||||
|
@ -270,18 +282,20 @@ _walk_pty(Termpty *ty)
|
|||
// int c0 = 0, c1 = 0;
|
||||
|
||||
if (!ty->back) return;
|
||||
for (i = 0; i < ty->backmax; i++)
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
{
|
||||
Termsavecomp *tsc = (Termsavecomp *)ty->back[i];
|
||||
Termsavecomp *tsc = (Termsavecomp *)&ty->back[i];
|
||||
|
||||
if (tsc)
|
||||
{
|
||||
ty->back[i] = _save_comp(ty->back[i]);
|
||||
#if 0
|
||||
ty->back[i] = _save_comp(tsc);
|
||||
tsc = (Termsavecomp *)ty->back[i];
|
||||
if (tsc->comp) ts_comp++;
|
||||
else ts_uncomp++;
|
||||
// c0 += tsc->w;
|
||||
// c1 += tsc->wout * sizeof(Termcell);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// printf("compress ratio: %1.3f\n", (double)c0 / (double)c1);
|
||||
|
@ -290,10 +304,14 @@ _walk_pty(Termpty *ty)
|
|||
static Eina_Bool
|
||||
_idler(void *data EINA_UNUSED)
|
||||
{
|
||||
/* TODO: RESIZE : re-enable compression */
|
||||
return EINA_FALSE;
|
||||
|
||||
Eina_List *l;
|
||||
Termpty *ty;
|
||||
// double t0, t;
|
||||
|
||||
|
||||
_mem_gen_next();
|
||||
|
||||
// t0 = ecore_time_get();
|
||||
|
@ -326,6 +344,8 @@ _timer(void *data EINA_UNUSED)
|
|||
static inline void
|
||||
_check_compressor(Eina_Bool frozen)
|
||||
{
|
||||
/* TODO: RESIZE re-enable compressor */
|
||||
return;
|
||||
if (freeze) return;
|
||||
if (idler) return;
|
||||
if ((ts_uncomp > 256) || (ts_freeops > 256))
|
||||
|
@ -395,11 +415,11 @@ termpty_save_extract(Termsave *ts)
|
|||
ts2->gen = _mem_gen_get();
|
||||
ts2->w = tsc->wout;
|
||||
buf = ((char *)tsc) + sizeof(Termsavecomp);
|
||||
bytes = LZ4_uncompress(buf, (char *)(&(ts2->cell[0])),
|
||||
bytes = LZ4_uncompress(buf, (char *)(&(ts2->cells[0])),
|
||||
tsc->wout * sizeof(Termcell));
|
||||
if (bytes < 0)
|
||||
{
|
||||
memset(&(ts2->cell[0]), 0, tsc->wout * sizeof(Termcell));
|
||||
memset(&(ts2->cells[0]), 0, tsc->wout * sizeof(Termcell));
|
||||
// ERR("Decompress problem in row at byte %i", -bytes);
|
||||
}
|
||||
if (ts->comp) ts_comp--;
|
||||
|
@ -417,10 +437,13 @@ termpty_save_extract(Termsave *ts)
|
|||
}
|
||||
|
||||
Termsave *
|
||||
termpty_save_new(int w)
|
||||
termpty_save_new(Termsave *ts, int w)
|
||||
{
|
||||
Termsave *ts = _ts_new(sizeof(Termsave) + ((w - 1) * sizeof(Termcell)));
|
||||
if (!ts) return NULL;
|
||||
termpty_save_free(ts);
|
||||
|
||||
Termcell *cells = calloc(1, w * sizeof(Termcell));
|
||||
if (!cells ) return NULL;
|
||||
ts->cells = cells;
|
||||
ts->gen = _mem_gen_get();
|
||||
ts->w = w;
|
||||
if (!ts_compfreeze) ts_uncomp++;
|
||||
|
@ -428,6 +451,21 @@ termpty_save_new(int w)
|
|||
return ts;
|
||||
}
|
||||
|
||||
Termsave *
|
||||
termpty_save_expand(Termsave *ts, Termcell *cells, ssize_t delta)
|
||||
{
|
||||
Termcell *newcells;
|
||||
|
||||
newcells = realloc(ts->cells, (ts->w + delta) * sizeof(Termcell));
|
||||
if (!newcells)
|
||||
return NULL;
|
||||
newcells[ts->w - 1].att.autowrapped = 0;
|
||||
memcpy(&newcells[ts->w], cells, delta * sizeof(Termcell));
|
||||
ts->w += delta;
|
||||
ts->cells = newcells;
|
||||
return ts;
|
||||
}
|
||||
|
||||
void
|
||||
termpty_save_free(Termsave *ts)
|
||||
{
|
||||
|
@ -438,6 +476,8 @@ termpty_save_free(Termsave *ts)
|
|||
else ts_uncomp--;
|
||||
ts_freeops++;
|
||||
}
|
||||
_ts_free(ts);
|
||||
_ts_free(ts->cells);
|
||||
ts->cells = NULL;
|
||||
ts->w = 0;
|
||||
_check_compressor(EINA_FALSE);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ void termpty_save_thaw(void);
|
|||
void termpty_save_register(Termpty *ty);
|
||||
void termpty_save_unregister(Termpty *ty);
|
||||
Termsave *termpty_save_extract(Termsave *ts);
|
||||
Termsave *termpty_save_new(int w);
|
||||
Termsave *termpty_save_new(Termsave *ts, int w);
|
||||
void termpty_save_free(Termsave *ts);
|
||||
Termsave *termpty_save_expand(Termsave *ts, Termcell *cells, ssize_t delta);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue