diff --git a/src/bin/termpty.c b/src/bin/termpty.c index a4a7dca2..0a3a5f9d 100644 --- a/src/bin/termpty.c +++ b/src/bin/termpty.c @@ -255,6 +255,8 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd, int w, int h ty->screen2 = calloc(1, sizeof(Termcell) * ty->w * ty->h); if (!ty->screen2) goto err; + ty->circular_offset = 0; + ty->fd = posix_openpt(O_RDWR | O_NOCTTY); if (ty->fd < 0) goto err; if (grantpt(ty->fd) != 0) goto err; @@ -442,7 +444,8 @@ termpty_cellrow_get(Termpty *ty, int y, int *wret) { if (y >= ty->h) return NULL; *wret = ty->w; - return &(ty->screen[y * ty->w]); + /* fprintf(stderr, "getting: %i (%i, %i)\n", y, ty->circular_offset, ty->h); */ + return &(TERMPTY_SCREEN(ty, 0, y)); } if (y < -ty->backmax) return NULL; ts = ty->back[(ty->backmax + ty->backpos + y) % ty->backmax]; @@ -495,12 +498,13 @@ termpty_resize(Termpty *ty, int w, int h) if (ww > oldw) ww = oldw; if (hh > oldh) hh = oldh; + // FIXME: handle pointer copy here for (y = 0; y < hh; y++) { Termcell *c1, *c2; c1 = &(olds[y * oldw]); - c2 = &(ty->screen[y * ty->w]); + c2 = &(TERMPTY_SCREEN(ty, 0, y)); _termpty_text_copy(ty, c1, c2, ww); c1 = &(olds2[y * oldw]); @@ -508,6 +512,7 @@ termpty_resize(Termpty *ty, int w, int h) _termpty_text_copy(ty, c1, c2, ww); } + ty->circular_offset = 0; free(olds); free(olds2); diff --git a/src/bin/termpty.h b/src/bin/termpty.h index 08dad371..4e91db0d 100644 --- a/src/bin/termpty.h +++ b/src/bin/termpty.h @@ -105,6 +105,7 @@ struct _Termpty const char *cur_cmd; Termcell *screen, *screen2; Termsave **back; + int circular_offset; int backmax, backpos; int backscroll_num; int *buf; @@ -141,3 +142,6 @@ void termpty_backscroll_set(Termpty *ty, int size); pid_t termpty_pid_get(const Termpty *ty); extern int _termpty_log_dom; + +#define TERMPTY_SCREEN(Tpty, X, Y) \ + Tpty->screen[X + (((Y + Tpty->circular_offset) % Tpty->h) * Tpty->w)] diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c index b5590af6..b5be6db0 100644 --- a/src/bin/termptyesc.c +++ b/src/bin/termptyesc.c @@ -456,7 +456,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce) int x, lim; if (arg < 1) arg = 1; - cells = &(ty->screen[ty->state.cy * ty->w]); + cells = &(TERMPTY_SCREEN(ty, 0, ty->state.cy)); lim = ty->w - arg; for (x = ty->state.cx; x < (ty->w); x++) { @@ -705,8 +705,8 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce) { Termcell t; - t = ty->screen[i]; - ty->screen[i] = ty->screen2[i]; + t = ty->screen[(i + ty->circular_offset) % ty->h]; + ty->screen[(i + ty->circular_offset) % ty->h] = ty->screen2[i]; ty->screen2[i] = t; } ty->altbuf = !ty->altbuf; @@ -846,7 +846,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce) size = ty->w * cy + cx + 1; for (idx = size - 1; idx >= 0; idx--) { - if (ty->screen[cx + (cy * ty->w)].att.tab) arg--; + if (TERMPTY_SCREEN(ty, cx, cy).att.tab) arg--; cx--; if (cx < 0) { @@ -1211,7 +1211,7 @@ _termpty_handle_seq(Termpty *ty, Eina_Unicode *c, Eina_Unicode *ce) return 1; case 0x09: // HT '\t' (horizontal tab) DBG("->HT"); - ty->screen[ty->state.cx + (ty->state.cy * ty->w)].att.tab = 1; + TERMPTY_SCREEN(ty, ty->state.cx, ty->state.cy).att.tab = 1; ty->state.wrapnext = 0; ty->state.cx += 8; ty->state.cx = (ty->state.cx / 8) * 8; @@ -1224,7 +1224,7 @@ _termpty_handle_seq(Termpty *ty, Eina_Unicode *c, Eina_Unicode *ce) case 0x0c: // FF '\f' (form feed) DBG("->LF"); if (ty->state.had_cr) - ty->screen[ty->state.had_cr_x + (ty->state.had_cr_y * ty->w)].att.newline = 1; + TERMPTY_SCREEN(ty, ty->state.had_cr_x, ty->state.had_cr_y).att.newline = 1; ty->state.wrapnext = 0; if (ty->state.crlf) ty->state.cx = 0; ty->state.cy++; diff --git a/src/bin/termptyops.c b/src/bin/termptyops.c index c56fbdd3..945a4ef5 100644 --- a/src/bin/termptyops.c +++ b/src/bin/termptyops.c @@ -50,7 +50,7 @@ _text_save_top(Termpty *ty) if (ty->backmax <= 0) return; ts = malloc(sizeof(Termsave) + ((ty->w - 1) * sizeof(Termcell))); ts->w = ty->w; - _termpty_text_copy(ty, ty->screen, ts->cell, ty->w); + _termpty_text_copy(ty, &(TERMPTY_SCREEN(ty, 0, 0)), ts->cell, ty->w); if (!ty->back) ty->back = calloc(1, sizeof(Termsave *) * ty->backmax); if (ty->back[ty->backpos]) free(ty->back[ty->backpos]); ty->back[ty->backpos] = ts; @@ -89,14 +89,28 @@ _termpty_text_scroll(Termpty *ty) ty->cb.cancel_sel.func(ty->cb.cancel_sel.data); } DBG("... scroll!!!!! [%i->%i]", start_y, end_y); - cells2 = &(ty->screen[end_y * ty->w]); - for (y = start_y; y < end_y; y++) + + if (start_y == 0 && end_y == ty->h - 1) { - cells = &(ty->screen[y * ty->w]); - cells2 = &(ty->screen[(y + 1) * ty->w]); - _termpty_text_copy(ty, cells2, cells, ty->w); + // screen is a circular buffer now + cells2 = &(ty->screen[ty->circular_offset * ty->w]); + _text_clear(ty, cells2, ty->w, ' ', EINA_TRUE); + + ty->circular_offset++; + if (ty->circular_offset >= ty->h) + ty->circular_offset = 0; + } + else + { + cells2 = &(ty->screen[end_y * ty->w]); + for (y = start_y; y < end_y; y++) + { + cells = &(ty->screen[y * ty->w]); + cells2 = &(ty->screen[(y + 1) * ty->w]); + _termpty_text_copy(ty, cells2, cells, ty->w); + } + _text_clear(ty, cells2, ty->w, ' ', EINA_TRUE); } - _text_clear(ty, cells2, ty->w, ' ', EINA_TRUE); } void @@ -111,14 +125,29 @@ _termpty_text_scroll_rev(Termpty *ty) end_y = ty->state.scroll_y2 - 1; } DBG("... scroll rev!!!!! [%i->%i]", start_y, end_y); - cells = &(ty->screen[end_y * ty->w]); - for (y = end_y; y > start_y; y--) + + if (start_y == 0 && end_y == ty->h - 1) { - cells = &(ty->screen[(y - 1) * ty->w]); - cells2 = &(ty->screen[y * ty->w]); - _termpty_text_copy(ty, cells, cells2, ty->w); + // screen is a circular buffer now + ty->circular_offset--; + if (ty->circular_offset < 0) + ty->circular_offset = ty->h - 1; + + cells = &(ty->screen[ty->circular_offset * ty->w]); + _text_clear(ty, cells, ty->w, ' ', EINA_TRUE); + } + else + { + cells = &(TERMPTY_SCREEN(ty, 0, end_y)); + for (y = end_y; y > start_y; y--) + { + cells = &(TERMPTY_SCREEN(ty, 0, (y - 1))); + cells2 = &(TERMPTY_SCREEN(ty, 0, y)); + _termpty_text_copy(ty, cells, cells2, ty->w); + } + y = start_y; + _text_clear(ty, cells, ty->w, ' ', EINA_TRUE); } - _text_clear(ty, cells, ty->w, ' ', EINA_TRUE); } void @@ -153,7 +182,7 @@ _termpty_text_append(Termpty *ty, const Eina_Unicode *codepoints, int len) Termcell *cells; int i, j; - cells = &(ty->screen[ty->state.cy * ty->w]); + cells = &(TERMPTY_SCREEN(ty, 0, ty->state.cy)); for (i = 0; i < len; i++) { Eina_Unicode g; @@ -165,7 +194,7 @@ _termpty_text_append(Termpty *ty, const Eina_Unicode *codepoints, int len) ty->state.cx = 0; ty->state.cy++; _termpty_text_scroll_test(ty); - cells = &(ty->screen[ty->state.cy * ty->w]); + cells = &(TERMPTY_SCREEN(ty, 0, ty->state.cy)); } if (ty->state.insert) { @@ -235,7 +264,7 @@ _termpty_clear_line(Termpty *ty, Termpty_Clear mode, int limit) Termcell *cells; int n = 0; - cells = &(ty->screen[ty->state.cy * ty->w]); + cells = &(TERMPTY_SCREEN(ty, 0, ty->state.cy)); switch (mode) { case TERMPTY_CLR_END: @@ -260,24 +289,41 @@ _termpty_clear_screen(Termpty *ty, Termpty_Clear mode) { Termcell *cells; - cells = ty->screen; + cells = &(TERMPTY_SCREEN(ty, 0, 0)); switch (mode) { case TERMPTY_CLR_END: _termpty_clear_line(ty, mode, ty->w); if (ty->state.cy < (ty->h - 1)) { - cells = &(ty->screen[(ty->state.cy + 1) * ty->w]); + cells = &(TERMPTY_SCREEN(ty, 0, (ty->state.cy + 1))); _text_clear(ty, cells, ty->w * (ty->h - ty->state.cy - 1), 0, EINA_TRUE); } break; case TERMPTY_CLR_BEGIN: if (ty->state.cy > 0) - _text_clear(ty, cells, ty->w * ty->state.cy, 0, EINA_TRUE); + { + // First clear from circular > height, then from 0 to circular + int y = ty->state.cy + ty->circular_offset; + + if (y < ty->h) + { + _text_clear(ty, cells, ty->w * ty->state.cy, 0, EINA_TRUE); + } + else + { + int yt = y % ty->w; + int yb = ty->h - ty->circular_offset; + + _text_clear(ty, cells, ty->w * yb, 0, EINA_TRUE); + _text_clear(ty, ty->screen, ty->w * yt, 0, EINA_TRUE); + } + } _termpty_clear_line(ty, mode, ty->w); break; case TERMPTY_CLR_ALL: - _text_clear(ty, cells, ty->w * ty->h, 0, EINA_TRUE); + ty->circular_offset = 0; + _text_clear(ty, ty->screen, ty->w * ty->h, 0, EINA_TRUE); ty->state.scroll_y2 = 0; break; default: