forked from enlightenment/terminology
Rewrite reflow on resize
Summary: simplify code (treat every resize as a single case) and fill the lines from the bottom up Reviewers: billiob Differential Revision: https://phab.enlightenment.org/D355
This commit is contained in:
parent
fae338a84f
commit
d0c6c1d457
|
@ -605,695 +605,210 @@ termpty_line_length(const Termcell *cells, ssize_t nb_cells)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OLD_SCREEN(_X, _Y) \
|
static int
|
||||||
old_screen[_X + (((_Y + old_circular_offset) % old_h) * old_w)]
|
termpty_line_find_top(Termpty *ty, int y_end)
|
||||||
|
|
||||||
static void
|
|
||||||
_termpty_horizontally_expand(Termpty *ty, int old_w, int old_h,
|
|
||||||
Termcell *old_screen)
|
|
||||||
{
|
{
|
||||||
int i,
|
int y_start = y_end;
|
||||||
new_back_pos = 0,
|
Termsave *ts;
|
||||||
old_y,
|
|
||||||
old_x,
|
|
||||||
old_circular_offset = ty->circular_offset,
|
|
||||||
x = 0,
|
|
||||||
y = 0;
|
|
||||||
Termsave **new_back, *new_ts = NULL;
|
|
||||||
Eina_Bool rewrapping = EINA_FALSE;
|
|
||||||
|
|
||||||
if ((!ty->backmax) || (!ty->back)) goto expand_screen;
|
while (y_start > 0)
|
||||||
|
|
||||||
new_back = calloc(sizeof(Termsave *), ty->backmax);
|
|
||||||
if (!new_back) return;
|
|
||||||
|
|
||||||
termpty_save_freeze();
|
|
||||||
for (i = 0; i < ty->backmax; i++)
|
|
||||||
{
|
{
|
||||||
Termsave *ts;
|
if (TERMPTY_SCREEN(ty, ty->w - 1, y_start - 1).att.autowrapped)
|
||||||
|
y_start--;
|
||||||
if (ty->backscroll_num == ty->backmax - 1)
|
|
||||||
ts = termpty_save_extract(ty->back[(ty->backpos + i) % ty->backmax]);
|
|
||||||
else
|
else
|
||||||
ts = termpty_save_extract(ty->back[i]);
|
return y_start;
|
||||||
if (!ts) break;
|
|
||||||
|
|
||||||
if (!ts->w)
|
|
||||||
{
|
|
||||||
if (rewrapping)
|
|
||||||
{
|
|
||||||
rewrapping = EINA_FALSE;
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
new_back[new_back_pos++] = ts;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rewrapping)
|
|
||||||
{
|
|
||||||
int remaining_width = ty->w - new_ts->w;
|
|
||||||
int len = ts->w;
|
|
||||||
Termcell *cells = ts->cell;
|
|
||||||
|
|
||||||
if (new_ts->w)
|
|
||||||
{
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped = 0;
|
|
||||||
}
|
|
||||||
if (ts->w >= remaining_width)
|
|
||||||
{
|
|
||||||
termpty_cell_copy(ty, cells, new_ts->cell + new_ts->w,
|
|
||||||
remaining_width);
|
|
||||||
new_ts->w = ty->w;
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped = 1;
|
|
||||||
len -= remaining_width;
|
|
||||||
cells += remaining_width;
|
|
||||||
|
|
||||||
new_ts = termpty_save_new(ty->w);
|
|
||||||
new_ts->w = 0;
|
|
||||||
new_back[new_back_pos++] = new_ts;
|
|
||||||
}
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
termpty_cell_copy(ty, cells, new_ts->cell + new_ts->w, len);
|
|
||||||
new_ts->w += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
rewrapping = ts->cell[ts->w - 1].att.autowrapped;
|
|
||||||
if (!rewrapping) new_ts = NULL;
|
|
||||||
termpty_save_free(ts);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ts->cell[ts->w - 1].att.autowrapped)
|
|
||||||
{
|
|
||||||
rewrapping = EINA_TRUE;
|
|
||||||
new_ts = termpty_save_new(ty->w);
|
|
||||||
new_ts->w = ts->w;
|
|
||||||
termpty_cell_copy(ty, ts->cell, new_ts->cell, ts->w);
|
|
||||||
new_ts->cell[ts->w - 1].att.autowrapped = 0;
|
|
||||||
new_back[new_back_pos++] = new_ts;
|
|
||||||
termpty_save_free(ts);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
new_back[new_back_pos++] = ts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
while (-y_start < ty->backscroll_num)
|
||||||
if (new_back_pos >= ty->backmax)
|
|
||||||
{
|
{
|
||||||
ty->backscroll_num = ty->backmax - 1;
|
ts = termpty_save_extract(ty->back[(y_start + ty->backpos - 1 +
|
||||||
ty->backpos = 0;
|
ty->backmax) % ty->backmax]);
|
||||||
|
ty->back[(y_start + ty->backpos - 1 + ty->backmax) % ty->backmax] = ts;
|
||||||
|
if (ts->cell[ts->w - 1].att.autowrapped)
|
||||||
|
y_start--;
|
||||||
|
else
|
||||||
|
return y_start;
|
||||||
|
}
|
||||||
|
return y_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
termpty_line_rewrap(Termpty *ty, int y_start, int y_end,
|
||||||
|
Termcell *screen2, Termsave **back2,
|
||||||
|
int w2, int h2, int y2_end)
|
||||||
|
{
|
||||||
|
int x, x2, y, y2, y2_start;
|
||||||
|
int len, len_last, len_remaining, copy_width, ts2_width;
|
||||||
|
Termsave *ts, *ts2;
|
||||||
|
Termcell *line, *line2;
|
||||||
|
|
||||||
|
if (y_end >= 0)
|
||||||
|
{
|
||||||
|
len_last = termpty_line_length(&TERMPTY_SCREEN(ty, 0, y_end), ty->w);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ty->backscroll_num = new_back_pos;
|
ts = termpty_save_extract(ty->back[(y_end + ty->backpos +
|
||||||
ty->backpos = new_back_pos;
|
ty->backmax) % ty->backmax]);
|
||||||
|
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;
|
||||||
free(ty->back);
|
y2_start = y2_end;
|
||||||
ty->back = new_back;
|
if (len_remaining)
|
||||||
|
|
||||||
expand_screen:
|
|
||||||
|
|
||||||
if (ty->altbuf)
|
|
||||||
{
|
{
|
||||||
termpty_save_thaw();
|
y2_start -= (len_remaining + w2 - 1) / w2 - 1;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ty->circular_offset = 0;
|
|
||||||
/* TODO double-width :) */
|
|
||||||
for (old_y = 0; old_y < old_h; old_y++)
|
|
||||||
{
|
|
||||||
ssize_t cur_line_length;
|
|
||||||
|
|
||||||
cur_line_length = termpty_line_length(&OLD_SCREEN(0, old_y), old_w);
|
|
||||||
if (rewrapping)
|
|
||||||
{
|
|
||||||
if (new_ts)
|
|
||||||
{
|
|
||||||
ssize_t remaining_width = ty->w - new_ts->w;
|
|
||||||
ssize_t len = MIN(cur_line_length, remaining_width);
|
|
||||||
Termcell *cells = &OLD_SCREEN(0, old_y);
|
|
||||||
|
|
||||||
termpty_cell_copy(ty, cells, new_ts->cell + new_ts->w, len);
|
|
||||||
new_ts->w += len;
|
|
||||||
cells += len;
|
|
||||||
if (cur_line_length > remaining_width)
|
|
||||||
{
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped = 1;
|
|
||||||
new_ts = NULL;
|
|
||||||
len = cur_line_length - remaining_width;
|
|
||||||
termpty_cell_copy(ty, cells, ty->screen + (y * ty->w),
|
|
||||||
len);
|
|
||||||
x += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
rewrapping = OLD_SCREEN(old_w - 1, old_y).att.autowrapped;
|
|
||||||
if (!rewrapping)
|
|
||||||
{
|
|
||||||
new_ts = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int remaining_width = ty->w - x,
|
|
||||||
len = cur_line_length;
|
|
||||||
|
|
||||||
old_x = 0;
|
|
||||||
if (cur_line_length >= remaining_width)
|
|
||||||
{
|
|
||||||
termpty_cell_copy(ty,
|
|
||||||
&OLD_SCREEN(0, old_y),
|
|
||||||
ty->screen + (y * ty->w) + x,
|
|
||||||
remaining_width);
|
|
||||||
TERMPTY_SCREEN(ty, ty->w - 1, y).att.autowrapped = 1;
|
|
||||||
y++;
|
|
||||||
x = 0;
|
|
||||||
old_x = remaining_width;
|
|
||||||
len -= remaining_width;
|
|
||||||
}
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
termpty_cell_copy(ty,
|
|
||||||
&OLD_SCREEN(old_x, old_y),
|
|
||||||
ty->screen + (y * ty->w) + x,
|
|
||||||
len);
|
|
||||||
x += len;
|
|
||||||
TERMPTY_SCREEN(ty, x - 1, y).att.autowrapped = 0;
|
|
||||||
}
|
|
||||||
rewrapping = OLD_SCREEN(old_w - 1, old_y).att.autowrapped;
|
|
||||||
if (!rewrapping) y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
termpty_cell_copy(ty,
|
|
||||||
&OLD_SCREEN(0, old_y),
|
|
||||||
ty->screen + (y * ty->w),
|
|
||||||
cur_line_length);
|
|
||||||
if (OLD_SCREEN(old_w - 1, old_y).att.autowrapped)
|
|
||||||
{
|
|
||||||
rewrapping = EINA_TRUE;
|
|
||||||
TERMPTY_SCREEN(ty, old_w - 1, old_y).att.autowrapped = 0;
|
|
||||||
x = cur_line_length;
|
|
||||||
}
|
|
||||||
else y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (y < old_h)
|
|
||||||
{
|
|
||||||
ty->state.cy -= old_h - y;
|
|
||||||
if (ty->state.cy < 0) ty->state.cy = 0;
|
|
||||||
}
|
|
||||||
termpty_save_thaw();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_termpty_vertically_expand(Termpty *ty, int old_w, int old_h,
|
|
||||||
Termcell *old_screen)
|
|
||||||
{
|
|
||||||
int from_history = 0, y;
|
|
||||||
|
|
||||||
if (ty->altbuf) return;
|
|
||||||
|
|
||||||
termpty_save_freeze();
|
|
||||||
|
|
||||||
if (ty->backmax > 0)
|
|
||||||
from_history = MIN(ty->h - old_h, ty->backscroll_num);
|
|
||||||
if (old_screen)
|
|
||||||
{
|
|
||||||
int old_circular_offset = ty->circular_offset;
|
|
||||||
|
|
||||||
ty->circular_offset = 0;
|
|
||||||
|
|
||||||
for (y = 0; y < old_h; y++)
|
|
||||||
{
|
|
||||||
Termcell *c1, *c2;
|
|
||||||
|
|
||||||
c1 = &(OLD_SCREEN(0, y));
|
|
||||||
c2 = &(TERMPTY_SCREEN(ty, 0, y));
|
|
||||||
termpty_cell_copy(ty, c1, c2, old_w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((from_history <= 0) || (!ty->back))
|
|
||||||
{
|
|
||||||
termpty_save_thaw();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* display content from backlog */
|
|
||||||
for (y = from_history - 1; y >= 0; y--)
|
|
||||||
{
|
|
||||||
Termsave *ts;
|
|
||||||
Termcell *src, *dst;
|
|
||||||
|
|
||||||
ty->backpos--;
|
|
||||||
if (ty->backpos < 0)
|
|
||||||
ty->backpos = ty->backscroll_num - 1;
|
|
||||||
ts = termpty_save_extract(ty->back[ty->backpos]);
|
|
||||||
|
|
||||||
src = ts->cell;
|
|
||||||
dst = &(TERMPTY_SCREEN(ty, 0, ty->h - from_history + y));
|
|
||||||
termpty_cell_copy(ty, src, dst, ts->w);
|
|
||||||
|
|
||||||
termpty_save_free(ts);
|
|
||||||
ty->back[ty->backpos] = NULL;
|
|
||||||
ty->backscroll_num--;
|
|
||||||
}
|
|
||||||
|
|
||||||
ty->circular_offset = (ty->circular_offset + ty->h - from_history) % ty->h;
|
|
||||||
|
|
||||||
ty->state.cy += from_history;
|
|
||||||
termpty_save_thaw();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
_termpty_vertically_shrink(Termpty *ty, int old_w, int old_h,
|
|
||||||
Termcell *old_screen)
|
|
||||||
{
|
|
||||||
int to_history,
|
|
||||||
real_h = old_h,
|
|
||||||
old_circular_offset,
|
|
||||||
y;
|
|
||||||
Termcell *src, *dst;
|
|
||||||
|
|
||||||
if (ty->altbuf) return;
|
|
||||||
|
|
||||||
termpty_save_freeze();
|
|
||||||
|
|
||||||
old_circular_offset = ty->circular_offset;
|
|
||||||
for (y = old_h - 1; y >= 0; y--)
|
|
||||||
{
|
|
||||||
ssize_t screen_length = termpty_line_length(&OLD_SCREEN(0, y), old_w);
|
|
||||||
|
|
||||||
if (screen_length) break;
|
|
||||||
else real_h--;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_history = real_h - ty->h;
|
|
||||||
if (to_history > 0)
|
|
||||||
{
|
|
||||||
for (y = 0; y < to_history; y++)
|
|
||||||
{
|
|
||||||
termpty_text_save_top(ty, &(OLD_SCREEN(0, y)), old_w);
|
|
||||||
}
|
|
||||||
ty->state.cy -= to_history;
|
|
||||||
if (ty->state.cy < 0) ty->state.cy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_w == ty->w)
|
|
||||||
{
|
|
||||||
if (to_history < 0)
|
|
||||||
to_history = 0;
|
|
||||||
ty->circular_offset = 0;
|
|
||||||
for (y = 0; y < ty->h; y++)
|
|
||||||
{
|
|
||||||
src = &(OLD_SCREEN(0, y + to_history));
|
|
||||||
dst = &(TERMPTY_SCREEN(ty, 0, y));
|
|
||||||
termpty_cell_copy(ty, src, dst, old_w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* in place */
|
if (y2_start < 0)
|
||||||
int len, pos, offset;
|
back2[y2_start + ty->backmax] = termpty_save_new(0);
|
||||||
|
return y2_start;
|
||||||
if ((to_history <= 0) || (ty->circular_offset == 0))
|
|
||||||
{
|
|
||||||
termpty_save_thaw();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ty->circular_offset = (ty->circular_offset + to_history) % old_h;
|
|
||||||
len = real_h - to_history;
|
|
||||||
pos = (len + ty->circular_offset) % old_h;
|
|
||||||
offset = len - pos;
|
|
||||||
|
|
||||||
/* 2 times */
|
|
||||||
if (offset > 0)
|
|
||||||
{
|
|
||||||
for (y = pos - 1; y >= 0; y--)
|
|
||||||
{
|
|
||||||
src = &(old_screen[y * old_w]);
|
|
||||||
dst = &(old_screen[(y + offset) * old_w]);
|
|
||||||
termpty_cell_copy(ty, src, dst, old_w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
offset = len;
|
|
||||||
|
|
||||||
for (y = 0; y < offset; y++)
|
|
||||||
{
|
|
||||||
src = &(old_screen[(ty->circular_offset + y) * old_w]);
|
|
||||||
dst = &(old_screen[y * old_w]);
|
|
||||||
termpty_cell_copy(ty, src, dst, old_w);
|
|
||||||
}
|
|
||||||
ty->circular_offset = 0;
|
|
||||||
|
|
||||||
len = ty->h - len;
|
|
||||||
if (len)
|
|
||||||
termpty_cell_fill(ty, NULL,
|
|
||||||
&old_screen[(old_h - len) * old_w],
|
|
||||||
len * old_w);
|
|
||||||
}
|
}
|
||||||
termpty_save_thaw();
|
if (-y2_start > ty->backmax)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
_termpty_horizontally_shrink(Termpty *ty, int old_w, int old_h,
|
|
||||||
Termcell *old_screen)
|
|
||||||
{
|
|
||||||
int i,
|
|
||||||
new_back_pos = 0,
|
|
||||||
new_back_scroll_num = 0,
|
|
||||||
old_y,
|
|
||||||
old_x,
|
|
||||||
screen_height_used,
|
|
||||||
old_circular_offset = ty->circular_offset,
|
|
||||||
x = 0,
|
|
||||||
y = 0;
|
|
||||||
ssize_t *screen_lengths;
|
|
||||||
Termsave **new_back,
|
|
||||||
*new_ts = NULL,
|
|
||||||
*old_ts = NULL;
|
|
||||||
Termcell *old_cells = NULL;
|
|
||||||
Eina_Bool rewrapping = EINA_FALSE,
|
|
||||||
done = EINA_FALSE,
|
|
||||||
cy_pushed_back = EINA_FALSE;
|
|
||||||
|
|
||||||
termpty_save_freeze();
|
|
||||||
|
|
||||||
if (!ty->backmax || !ty->back)
|
|
||||||
goto shrink_screen;
|
|
||||||
|
|
||||||
new_back = calloc(sizeof(Termsave*), ty->backmax);
|
|
||||||
|
|
||||||
for (i = 0; i < ty->backmax; i++)
|
|
||||||
{
|
{
|
||||||
Termsave *ts;
|
y_start += ((-y2_start - ty->backmax) * w2) / ty->w;
|
||||||
Termcell *cells;
|
x = ((-y2_start - ty->backmax) * w2) % ty->w;
|
||||||
int remaining_width;
|
len_remaining -= (-y2_start - ty->backmax) * w2;
|
||||||
|
y2_start = -ty->backmax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
y = y_start;
|
||||||
|
x2 = 0;
|
||||||
|
y2 = y2_start;
|
||||||
|
|
||||||
if (ty->backscroll_num == ty->backmax - 1)
|
while (y <= y_end)
|
||||||
ts = termpty_save_extract(ty->back[(ty->backpos + i) % ty->backmax]);
|
{
|
||||||
else
|
if (y >= 0)
|
||||||
ts = termpty_save_extract(ty->back[i]);
|
|
||||||
if (!ts)
|
|
||||||
break;
|
|
||||||
|
|
||||||
#define PUSH_BACK_TS(_ts) do { \
|
|
||||||
if (new_back[new_back_pos]) \
|
|
||||||
termpty_save_free(new_back[new_back_pos]); \
|
|
||||||
new_back[new_back_pos++] = _ts; \
|
|
||||||
new_back_scroll_num++; \
|
|
||||||
if (new_back_pos >= ty->backmax) \
|
|
||||||
new_back_pos = 0; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
if (!ts->w)
|
|
||||||
{
|
{
|
||||||
if (rewrapping)
|
line = &TERMPTY_SCREEN(ty, 0, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ts = termpty_save_extract(ty->back[(y + ty->backpos +
|
||||||
|
ty->backmax) % ty->backmax]);
|
||||||
|
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, w2 - x2);
|
||||||
|
if (x2 == 0)
|
||||||
{
|
{
|
||||||
rewrapping = EINA_FALSE;
|
if (y2 >= 0)
|
||||||
new_ts = termpty_save_new(old_ts->w);
|
|
||||||
termpty_cell_copy(ty, old_cells, new_ts->cell, old_ts->w);
|
|
||||||
PUSH_BACK_TS(new_ts);
|
|
||||||
termpty_save_free(old_ts);
|
|
||||||
old_ts = NULL;
|
|
||||||
termpty_save_free(ts);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PUSH_BACK_TS(ts);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!old_ts && ts->w <= ty->w)
|
|
||||||
{
|
|
||||||
PUSH_BACK_TS(ts);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cells = ts->cell;
|
|
||||||
|
|
||||||
if (old_ts)
|
|
||||||
{
|
|
||||||
int len = MIN(old_ts->w + ts->w, ty->w);
|
|
||||||
|
|
||||||
new_ts = termpty_save_new(len);
|
|
||||||
termpty_cell_copy(ty, old_cells, new_ts->cell, old_ts->w);
|
|
||||||
|
|
||||||
remaining_width = len - old_ts->w;
|
|
||||||
|
|
||||||
termpty_cell_copy(ty, cells, new_ts->cell + old_ts->w,
|
|
||||||
remaining_width);
|
|
||||||
|
|
||||||
rewrapping = ts->cell[ts->w - 1].att.autowrapped;
|
|
||||||
cells += remaining_width;
|
|
||||||
ts->w -= remaining_width;
|
|
||||||
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped =
|
|
||||||
rewrapping || ts->w > 0;
|
|
||||||
|
|
||||||
termpty_save_free(old_ts);
|
|
||||||
old_ts = NULL;
|
|
||||||
|
|
||||||
PUSH_BACK_TS(new_ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ts->w >= ty->w)
|
|
||||||
{
|
|
||||||
new_ts = termpty_save_new(ty->w);
|
|
||||||
termpty_cell_copy(ty, cells, new_ts->cell, ty->w);
|
|
||||||
rewrapping = ts->cell[ts->w - 1].att.autowrapped;
|
|
||||||
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped = 1;
|
|
||||||
if (!rewrapping && ty->w == ts->w)
|
|
||||||
new_ts->cell[new_ts->w - 1].att.autowrapped = 0;
|
|
||||||
|
|
||||||
cells += ty->w;
|
|
||||||
ts->w -= ty->w;
|
|
||||||
|
|
||||||
PUSH_BACK_TS(new_ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ts->w)
|
|
||||||
{
|
|
||||||
old_cells = 0;
|
|
||||||
termpty_save_free(old_ts);
|
|
||||||
old_ts = NULL;
|
|
||||||
rewrapping = EINA_FALSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rewrapping)
|
|
||||||
{
|
|
||||||
old_cells = cells;
|
|
||||||
old_ts = ts;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_ts = termpty_save_new(ts->w);
|
|
||||||
termpty_cell_copy(ty, cells, new_ts->cell, ts->w);
|
|
||||||
PUSH_BACK_TS(new_ts);
|
|
||||||
termpty_save_free(ts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#undef PUSH_BACK_TS
|
|
||||||
|
|
||||||
ty->backpos = new_back_pos;
|
|
||||||
ty->backscroll_num = new_back_scroll_num;
|
|
||||||
if (ty->backscroll_num >= ty->backmax)
|
|
||||||
ty->backscroll_num = ty->backmax - 1;
|
|
||||||
free(ty->back);
|
|
||||||
ty->back = new_back;
|
|
||||||
|
|
||||||
shrink_screen:
|
|
||||||
|
|
||||||
if (ty->altbuf)
|
|
||||||
{
|
|
||||||
termpty_save_thaw();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ty->circular_offset = 0;
|
|
||||||
|
|
||||||
/* TODO double-width :) */
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
|
|
||||||
if (old_ts)
|
|
||||||
{
|
|
||||||
termpty_cell_copy(ty, old_cells, ty->screen, old_ts->w);
|
|
||||||
x = old_ts->w;
|
|
||||||
if (!rewrapping) y++;
|
|
||||||
termpty_save_free(old_ts);
|
|
||||||
old_ts = NULL;
|
|
||||||
old_cells = NULL;
|
|
||||||
}
|
|
||||||
screen_height_used = old_h;
|
|
||||||
screen_lengths = malloc(sizeof(ssize_t) * old_h);
|
|
||||||
for (old_y = old_h - 1; old_y >= 0; old_y--)
|
|
||||||
{
|
|
||||||
screen_lengths[old_y] = termpty_line_length(&OLD_SCREEN(0, old_y), old_w);
|
|
||||||
|
|
||||||
if (!screen_lengths[old_y] && done != EINA_TRUE)
|
|
||||||
screen_height_used--;
|
|
||||||
else
|
|
||||||
done = EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (old_y = 0; old_y < screen_height_used; old_y++)
|
|
||||||
{
|
|
||||||
ssize_t cur_line_length;
|
|
||||||
int remaining_width, len;
|
|
||||||
|
|
||||||
cur_line_length = screen_lengths[old_y];
|
|
||||||
|
|
||||||
if (old_y == ty->state.cy)
|
|
||||||
ty->state.cy = y;
|
|
||||||
|
|
||||||
old_x = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Eina_Bool need_new_line = EINA_FALSE;
|
|
||||||
|
|
||||||
remaining_width = ty->w - x;
|
|
||||||
len = MIN(remaining_width, cur_line_length);
|
|
||||||
termpty_cell_copy(ty,
|
|
||||||
&OLD_SCREEN(old_x, old_y),
|
|
||||||
&TERMPTY_SCREEN(ty, x, y),
|
|
||||||
len);
|
|
||||||
x += len;
|
|
||||||
old_x += len;
|
|
||||||
cur_line_length -= len;
|
|
||||||
if (cur_line_length > 0)
|
|
||||||
{
|
|
||||||
TERMPTY_SCREEN(ty, x - 1, y).att.autowrapped = 1;
|
|
||||||
need_new_line = EINA_TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Termcell *cell = &TERMPTY_SCREEN(ty, x - 1, y);
|
|
||||||
if (cell->att.autowrapped)
|
|
||||||
{
|
{
|
||||||
if (x >= ty->w)
|
line2 = screen2 + (y2 * w2);
|
||||||
need_new_line = EINA_TRUE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cell->att.autowrapped = 0;
|
|
||||||
need_new_line = EINA_FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (old_y < old_h - 1)
|
ts2_width = MIN(len_remaining, w2);
|
||||||
need_new_line = EINA_TRUE;
|
ts2 = termpty_save_new(ts2_width);
|
||||||
|
line2 = ts2->cell;
|
||||||
|
back2[y2 + ty->backmax] = ts2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (need_new_line)
|
termpty_cell_copy(ty, line + x, line2 + x2, copy_width);
|
||||||
|
x += copy_width;
|
||||||
|
x2 += copy_width;
|
||||||
|
len_remaining -= copy_width;
|
||||||
|
if ((x2 == w2) && (y2 != y2_end))
|
||||||
{
|
{
|
||||||
x = 0;
|
line2[x2 - 1].att.autowrapped = 1;
|
||||||
if (y >= ty->h - 1)
|
x2 = 0;
|
||||||
{
|
y2++;
|
||||||
Termcell *cells;
|
|
||||||
|
|
||||||
ty->circular_offset++;
|
|
||||||
if (ty->circular_offset >= ty->h)
|
|
||||||
ty->circular_offset = 0;
|
|
||||||
cells = &TERMPTY_SCREEN(ty, 0, y);
|
|
||||||
len = termpty_line_length(cells, ty->w);
|
|
||||||
termpty_text_save_top(ty, cells, len);
|
|
||||||
termpty_cell_fill(ty, NULL, cells, len);
|
|
||||||
if (ty->state.cy == old_y || cy_pushed_back)
|
|
||||||
{
|
|
||||||
cy_pushed_back = EINA_TRUE;
|
|
||||||
ty->state.cy--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
y++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (cur_line_length > 0);
|
x = 0;
|
||||||
|
y++;
|
||||||
}
|
}
|
||||||
if (ty->state.cy >= ty->h) ty->state.cy = ty->h - 1;
|
return y2_start;
|
||||||
else if (ty->state.cy < 0) ty->state.cy = 0;
|
|
||||||
|
|
||||||
termpty_save_thaw();
|
|
||||||
|
|
||||||
free(screen_lengths);
|
|
||||||
|
|
||||||
termpty_save_thaw();
|
|
||||||
}
|
}
|
||||||
#undef OLD_SCREEN
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
termpty_resize(Termpty *ty, int w, int h)
|
termpty_resize(Termpty *ty, int new_w, int new_h)
|
||||||
{
|
{
|
||||||
Termcell *olds, *olds2;
|
Termcell *new_screen;
|
||||||
int oldw, oldh;
|
Termsave **new_back;
|
||||||
|
int y_start, y_end, new_y_start, new_y_end;
|
||||||
|
int i;
|
||||||
|
|
||||||
if ((ty->w == w) && (ty->h == h)) return;
|
if ((ty->w == new_w) && (ty->h == new_h)) return;
|
||||||
|
if ((new_w == new_h) && (new_w == 1)) return;
|
||||||
|
|
||||||
if (w == h && h == 1) // fuck off
|
termpty_save_freeze();
|
||||||
return;
|
|
||||||
|
|
||||||
olds = ty->screen;
|
if (ty->altbuf)
|
||||||
olds2 = ty->screen2;
|
{
|
||||||
oldw = ty->w;
|
termpty_screen_swap(ty);
|
||||||
oldh = ty->h;
|
ty->altbuf = 1;
|
||||||
|
}
|
||||||
|
|
||||||
ty->w = w;
|
new_screen = calloc(1, sizeof(Termcell) * new_w * new_h);
|
||||||
ty->h = h;
|
|
||||||
ty->state.had_cr = 0;
|
|
||||||
|
|
||||||
ty->screen = calloc(1, sizeof(Termcell) * ty->w * ty->h);
|
|
||||||
if (!ty->screen)
|
if (!ty->screen)
|
||||||
{
|
{
|
||||||
ty->screen2 = NULL;
|
ty->screen2 = NULL;
|
||||||
ERR("memerr");
|
ERR("memerr");
|
||||||
}
|
}
|
||||||
ty->screen2 = calloc(1, sizeof(Termcell) * ty->w * ty->h);
|
free(ty->screen2);
|
||||||
|
ty->screen2 = calloc(1, sizeof(Termcell) * new_w * new_h);
|
||||||
if (!ty->screen2)
|
if (!ty->screen2)
|
||||||
{
|
{
|
||||||
ERR("memerr");
|
ERR("memerr");
|
||||||
}
|
}
|
||||||
|
new_back = calloc(sizeof(Termsave *), ty->backmax);
|
||||||
|
|
||||||
/* Shrink vertically, in place, if needed */
|
y_end = ty->state.cy;
|
||||||
if (ty->h < oldh)
|
y_start = termpty_line_find_top(ty, ty->state.cy);
|
||||||
|
new_y_start = new_h - 1 - (y_end - y_start);
|
||||||
|
new_y_end = new_y_start - 1;
|
||||||
|
y_end = y_start - 1;
|
||||||
|
if (new_y_end < 0)
|
||||||
|
new_y_end = -1;
|
||||||
|
while ((y_end >= -ty->backscroll_num) && (new_y_end >= -ty->backmax))
|
||||||
{
|
{
|
||||||
_termpty_vertically_shrink(ty, oldw, oldh, olds);
|
y_start = termpty_line_find_top(ty, y_end);
|
||||||
oldh = ty->h;
|
new_y_start = termpty_line_rewrap(ty, y_start, y_end, new_screen,
|
||||||
|
new_back, new_w, new_h, new_y_end);
|
||||||
|
y_end = y_start - 1;
|
||||||
|
new_y_end = new_y_start - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldw != ty->w)
|
free(ty->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->w = new_w;
|
||||||
|
ty->h = new_h;
|
||||||
|
ty->state.cy = MIN((new_h - 1) - new_y_start, new_h - 1);
|
||||||
|
ty->circular_offset = MAX(new_y_start, 0);
|
||||||
|
ty->backpos = 0;
|
||||||
|
ty->backscroll_num = MAX(-new_y_start, 0);
|
||||||
|
ty->state.had_cr = 0;
|
||||||
|
ty->screen = new_screen;
|
||||||
|
ty->back = new_back;
|
||||||
|
|
||||||
|
if (ty->altbuf)
|
||||||
{
|
{
|
||||||
if (ty->w > oldw)
|
termpty_screen_swap(ty);
|
||||||
_termpty_horizontally_expand(ty, oldw, oldh, olds);
|
ty->altbuf = 1;
|
||||||
else
|
|
||||||
_termpty_horizontally_shrink(ty, oldw, oldh, olds);
|
|
||||||
|
|
||||||
free(olds); olds = NULL;
|
|
||||||
free(olds2); olds2 = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ty->h > oldh)
|
|
||||||
_termpty_vertically_expand(ty, oldw, oldh, olds);
|
|
||||||
|
|
||||||
free(olds);
|
|
||||||
free(olds2);
|
|
||||||
|
|
||||||
_limit_coord(ty, &(ty->state));
|
_limit_coord(ty, &(ty->state));
|
||||||
_limit_coord(ty, &(ty->swap));
|
_limit_coord(ty, &(ty->swap));
|
||||||
_limit_coord(ty, &(ty->save));
|
_limit_coord(ty, &(ty->save));
|
||||||
|
|
||||||
_pty_size(ty);
|
_pty_size(ty);
|
||||||
|
|
||||||
|
termpty_save_thaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1484,31 +999,25 @@ termpty_cell_copy(Termpty *ty, Termcell *src, Termcell *dst, int n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_swap_line(Termpty *ty, Termcell *cells, Termcell *cells2)
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
Termcell c;
|
|
||||||
|
|
||||||
for (x = 0; x < ty->w; x++)
|
|
||||||
{
|
|
||||||
c = cells[x];
|
|
||||||
cells[x] = cells2[x];
|
|
||||||
cells2[x] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
termpty_screen_swap(Termpty *ty)
|
termpty_screen_swap(Termpty *ty)
|
||||||
{
|
{
|
||||||
int y;
|
Termcell *tmp_screen;
|
||||||
|
Termstate tmp_state;
|
||||||
|
int tmp_circular_offset;
|
||||||
|
|
||||||
|
tmp_screen = ty->screen;
|
||||||
|
ty->screen = ty->screen2;
|
||||||
|
ty->screen2 = tmp_screen;
|
||||||
|
|
||||||
|
tmp_state = ty->state;
|
||||||
|
ty->state = ty->swap;
|
||||||
|
ty->swap = tmp_state;
|
||||||
|
|
||||||
|
tmp_circular_offset = ty->circular_offset;
|
||||||
|
ty->circular_offset = ty->circular_offset2;
|
||||||
|
ty->circular_offset2 = tmp_circular_offset;
|
||||||
|
|
||||||
for (y = 0; y < ty->h; y++)
|
|
||||||
{
|
|
||||||
_swap_line(ty,
|
|
||||||
&(TERMPTY_SCREEN(ty, 0, y)),
|
|
||||||
&ty->screen2[y * ty->w]);
|
|
||||||
}
|
|
||||||
ty->altbuf = !ty->altbuf;
|
ty->altbuf = !ty->altbuf;
|
||||||
|
|
||||||
if (ty->cb.cancel_sel.func)
|
if (ty->cb.cancel_sel.func)
|
||||||
|
|
|
@ -123,6 +123,7 @@ struct _Termpty
|
||||||
int w, h;
|
int w, h;
|
||||||
int fd, slavefd;
|
int fd, slavefd;
|
||||||
int circular_offset;
|
int circular_offset;
|
||||||
|
int circular_offset2;
|
||||||
int backmax, backpos;
|
int backmax, backpos;
|
||||||
int backscroll_num;
|
int backscroll_num;
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -835,20 +835,12 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
handled = 1;
|
handled = 1;
|
||||||
DBG("DDD: switch buf");
|
DBG("DDD: switch buf");
|
||||||
if (ty->altbuf)
|
if (ty->altbuf)
|
||||||
{
|
// if we are looking at alt buf now,
|
||||||
// if we are looking at alt buf now,
|
// clear main buf before we swap it back
|
||||||
// clear main buf before we swap it back
|
// into the screen2 save (so save is
|
||||||
// into the screen2 save (so save is
|
// clear)
|
||||||
// clear)
|
_termpty_clear_all(ty);
|
||||||
_termpty_clear_all(ty);
|
|
||||||
// _termpty_cursor_copy(&(ty->swap), &(ty->state));
|
|
||||||
ty->state = ty->swap;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// _termpty_cursor_copy(&(ty->state), &(ty->swap));
|
|
||||||
ty->swap = ty->state;
|
|
||||||
}
|
|
||||||
// swap screen content now
|
// swap screen content now
|
||||||
termpty_screen_swap(ty);
|
termpty_screen_swap(ty);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -55,7 +55,7 @@ termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
|
||||||
ty->backpos++;
|
ty->backpos++;
|
||||||
if (ty->backpos >= ty->backmax) ty->backpos = 0;
|
if (ty->backpos >= ty->backmax) ty->backpos = 0;
|
||||||
ty->backscroll_num++;
|
ty->backscroll_num++;
|
||||||
if (ty->backscroll_num >= ty->backmax) ty->backscroll_num = ty->backmax - 1;
|
if (ty->backscroll_num >= ty->backmax) ty->backscroll_num = ty->backmax;
|
||||||
termpty_save_thaw();
|
termpty_save_thaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue