summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2015-04-06 18:08:23 +0200
committerBoris Faure <billiob@gmail.com>2015-08-03 20:43:17 +0200
commit34592ab5b3e01e473355c9cc0f370cee0731c40c (patch)
tree156898a04da3a9edd4b5c7cba7d249b861f8c1ec /src
parent4378f871629abdb72877ba2a12d520138bba89e0 (diff)
new resize/backlog implementation. Closes T2461
idea: store full lines in the backlog. No need to change them on resize
Diffstat (limited to 'src')
-rw-r--r--src/bin/miniview.c9
-rw-r--r--src/bin/termio.c22
-rw-r--r--src/bin/termpty.c487
-rw-r--r--src/bin/termpty.h12
-rw-r--r--src/bin/termptyops.c42
-rw-r--r--src/bin/termptysave.c66
-rw-r--r--src/bin/termptysave.h3
7 files changed, 360 insertions, 281 deletions
diff --git a/src/bin/miniview.c b/src/bin/miniview.c
index 06dc287..90b3477 100644
--- a/src/bin/miniview.c
+++ b/src/bin/miniview.c
@@ -139,12 +139,12 @@ _draw_line(const Termpty *ty, unsigned int *pixels,
139Eina_Bool 139Eina_Bool
140_is_top_bottom_reached(Miniview *mv) 140_is_top_bottom_reached(Miniview *mv)
141{ 141{
142 Termpty *ty;
143 int history_len; 142 int history_len;
144 143
145 EINA_SAFETY_ON_NULL_RETURN_VAL(mv, EINA_FALSE); 144 EINA_SAFETY_ON_NULL_RETURN_VAL(mv, EINA_FALSE);
146 ty = termio_pty_get(mv->termio); 145
147 history_len = ty->backscroll_num; 146 /* TODO: RESIZE */
147 history_len = 42; //termpty_backscroll_len_get(ty);
148 148
149 if (( (- mv->img_hist) > (int)(mv->img_h - mv->rows - (mv->rows / 2))) && 149 if (( (- mv->img_hist) > (int)(mv->img_h - mv->rows - (mv->rows / 2))) &&
150 ( (- mv->img_hist) < (int)(history_len + (mv->rows / 2)))) 150 ( (- mv->img_hist) < (int)(history_len + (mv->rows / 2))))
@@ -522,7 +522,8 @@ _deferred_renderer(void *data)
522 evas_object_geometry_get(mv->termio, &ox, &oy, &ow, &oh); 522 evas_object_geometry_get(mv->termio, &ox, &oy, &ow, &oh);
523 if ((ow == 0) || (oh == 0)) return EINA_TRUE; 523 if ((ow == 0) || (oh == 0)) return EINA_TRUE;
524 524
525 history_len = ty->backscroll_num; 525 /* TODO: RESIZE */
526 history_len = 42; //termpty_backscroll_len_get(ty);
526 527
527 evas_object_image_size_set(mv->img, mv->cols, mv->img_h); 528 evas_object_image_size_set(mv->img, mv->cols, mv->img_h);
528 ow = mv->cols; 529 ow = mv->cols;
diff --git a/src/bin/termio.c b/src/bin/termio.c
index ffdd7e7..c964079 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -133,8 +133,6 @@ termio_scroll(Evas_Object *obj, int direction, int start_y, int end_y)
133 if (mv) miniview_position_offset(mv, direction, EINA_FALSE); 133 if (mv) miniview_position_offset(mv, direction, EINA_FALSE);
134 // adjust scroll position for added scrollback 134 // adjust scroll position for added scrollback
135 sd->scroll -= direction; 135 sd->scroll -= direction;
136 if (sd->scroll > sd->pty->backscroll_num)
137 sd->scroll = sd->pty->backscroll_num;
138 } 136 }
139 ty = sd->pty; 137 ty = sd->pty;
140 if (ty->selection.is_active) 138 if (ty->selection.is_active)
@@ -347,15 +345,8 @@ termio_scroll_delta(Evas_Object *obj, int delta, int by_page)
347 delta *= by; 345 delta *= by;
348 } 346 }
349 sd->scroll += delta; 347 sd->scroll += delta;
350 if (delta > 0) 348 if (delta <= 0 && sd->scroll < 0)
351 { 349 sd->scroll = 0;
352 if (sd->scroll > sd->pty->backscroll_num)
353 sd->scroll = sd->pty->backscroll_num;
354 }
355 else
356 {
357 if (sd->scroll < 0) sd->scroll = 0;
358 }
359 _smart_update_queue(obj, sd); 350 _smart_update_queue(obj, sd);
360 miniview_position_offset(term_miniview_get(sd->term), -delta, EINA_TRUE); 351 miniview_position_offset(term_miniview_get(sd->term), -delta, EINA_TRUE);
361} 352}
@@ -2050,6 +2041,7 @@ termio_selection_get(Evas_Object *obj, int c1x, int c1y, int c2x, int c2y,
2050 2041
2051 EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL); 2042 EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL);
2052 termpty_cellcomp_freeze(sd->pty); 2043 termpty_cellcomp_freeze(sd->pty);
2044 /* TODO: RESIZE use/save the reference point */
2053 for (y = c1y; y <= c2y; y++) 2045 for (y = c1y; y <= c2y; y++)
2054 { 2046 {
2055 Termcell *cells; 2047 Termcell *cells;
@@ -4127,8 +4119,6 @@ _mouse_selection_scroll(void *data)
4127 if (cy == 0) 4119 if (cy == 0)
4128 cy = -1; 4120 cy = -1;
4129 sd->scroll -= cy; 4121 sd->scroll -= cy;
4130 if (sd->scroll > sd->pty->backscroll_num)
4131 sd->scroll = sd->pty->backscroll_num;
4132 sd->pty->selection.end.y = -sd->scroll; 4122 sd->pty->selection.end.y = -sd->scroll;
4133 _smart_update_queue(data, sd); 4123 _smart_update_queue(data, sd);
4134 } 4124 }
@@ -4324,9 +4314,8 @@ _smart_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNU
4324 else 4314 else
4325 { 4315 {
4326 sd->scroll -= (ev->z * 4); 4316 sd->scroll -= (ev->z * 4);
4327 if (sd->scroll > sd->pty->backscroll_num) 4317 if (sd->scroll < 0)
4328 sd->scroll = sd->pty->backscroll_num; 4318 sd->scroll = 0;
4329 else if (sd->scroll < 0) sd->scroll = 0;
4330 _smart_update_queue(data, sd); 4319 _smart_update_queue(data, sd);
4331 miniview_position_offset(term_miniview_get(sd->term), 4320 miniview_position_offset(term_miniview_get(sd->term),
4332 ev->z * 4, EINA_TRUE); 4321 ev->z * 4, EINA_TRUE);
@@ -4520,6 +4509,7 @@ _smart_apply(Evas_Object *obj)
4520 } 4509 }
4521 inv = sd->pty->termstate.reverse; 4510 inv = sd->pty->termstate.reverse;
4522 termpty_cellcomp_freeze(sd->pty); 4511 termpty_cellcomp_freeze(sd->pty);
4512 termpty_backscroll_adjust(sd->pty, &sd->scroll);
4523 for (y = 0; y < sd->grid.h; y++) 4513 for (y = 0; y < sd->grid.h; y++)
4524 { 4514 {
4525 Termcell *cells; 4515 Termcell *cells;
diff --git a/src/bin/termpty.c b/src/bin/termpty.c
index 5e49ba4..9a0a143 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -19,6 +19,7 @@
19#if defined (__sun) || defined (__sun__) 19#if defined (__sun) || defined (__sun__)
20# include <stropts.h> 20# include <stropts.h>
21#endif 21#endif
22#include <assert.h>
22 23
23/* specific log domain to help debug only terminal code parser */ 24/* specific log domain to help debug only terminal code parser */
24int _termpty_log_dom = -1; 25int _termpty_log_dom = -1;
@@ -298,7 +299,7 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd,
298 if (!ty) return NULL; 299 if (!ty) return NULL;
299 ty->w = w; 300 ty->w = w;
300 ty->h = h; 301 ty->h = h;
301 ty->backmax = backscroll; 302 ty->backsize = backscroll;
302 303
303 termpty_reset_state(ty); 304 termpty_reset_state(ty);
304 305
@@ -567,16 +568,9 @@ termpty_free(Termpty *ty)
567 { 568 {
568 int i; 569 int i;
569 570
570 for (i = 0; i < ty->backmax; i++) 571 for (i = 0; i < ty->backsize; i++)
571 { 572 termpty_save_free(&ty->back[i]);
572 if (ty->back[i])
573 {
574 termpty_save_free(ty->back[i]);
575 ty->back[i] = NULL;
576 }
577 }
578 free(ty->back); 573 free(ty->back);
579 ty->back = NULL;
580 } 574 }
581 free(ty->screen); 575 free(ty->screen);
582 free(ty->screen2); 576 free(ty->screen2);
@@ -596,6 +590,24 @@ termpty_cellcomp_thaw(Termpty *ty EINA_UNUSED)
596 termpty_save_thaw(); 590 termpty_save_thaw();
597} 591}
598 592
593static Eina_Bool
594termpty_line_is_empty(const Termcell *cells, ssize_t nb_cells)
595{
596 ssize_t len = nb_cells;
597
598 for (len = nb_cells - 1; len >= 0; len--)
599 {
600 const Termcell *cell = cells + len;
601
602 if ((cell->codepoint != 0) &&
603 (cell->att.bg != COL_INVIS))
604 return EINA_FALSE;
605 }
606
607 return EINA_TRUE;
608}
609
610
599ssize_t 611ssize_t
600termpty_line_length(const Termcell *cells, ssize_t nb_cells) 612termpty_line_length(const Termcell *cells, ssize_t nb_cells)
601{ 613{
@@ -613,6 +625,48 @@ termpty_line_length(const Termcell *cells, ssize_t nb_cells)
613 return 0; 625 return 0;
614} 626}
615 627
628#define BACKLOG_ROW_GET(Ty, Y) \
629 (&Ty->back[(Ty->backsize + ty->backpos - (Y)) % Ty->backsize])
630
631void
632termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
633{
634 Termsave *ts;
635 ssize_t w;
636
637 if (ty->backsize <= 0)
638 return;
639 assert(ty->back);
640
641 termpty_save_freeze();
642
643 w = termpty_line_length(cells, w_max);
644 if (ty->backsize >= 1)
645 {
646 ts = BACKLOG_ROW_GET(ty, 0);
647 if (!ts->cells)
648 goto add_new_ts;
649 /* TODO: RESIZE uncompress ? */
650 if (ts->w && ts->cells[ts->w - 1].att.autowrapped)
651 {
652 termpty_save_expand(ts, cells, w);
653 return;
654 }
655 }
656
657add_new_ts:
658 ts = BACKLOG_ROW_GET(ty, -1);
659 ts = termpty_save_new(ts, w);
660 if (!ts)
661 return;
662 termpty_cell_copy(ty, cells, ts->cells, w);
663 ty->backpos++;
664 if (ty->backpos >= ty->backsize)
665 ty->backpos = 0;
666 termpty_save_thaw();
667}
668
669
616ssize_t 670ssize_t
617termpty_row_length(Termpty *ty, int y) 671termpty_row_length(Termpty *ty, int y)
618{ 672{
@@ -629,38 +683,114 @@ termpty_row_length(Termpty *ty, int y)
629 cells = &(TERMPTY_SCREEN(ty, 0, y)); 683 cells = &(TERMPTY_SCREEN(ty, 0, y));
630 return termpty_line_length(cells, ty->w); 684 return termpty_line_length(cells, ty->w);
631 } 685 }
632 if ((y < -ty->backmax) || !ty->back) 686 if ((y < -ty->backsize) || !ty->back)
633 { 687 {
634 ERR("invalid row given"); 688 ERR("invalid row given");
635 return 0; 689 return 0;
636 } 690 }
637 ts = ty->back[(ty->backmax + ty->backpos + y) % ty->backmax]; 691 ts = BACKLOG_ROW_GET(ty, y);
638 if (!ts) return 0;
639 692
640 return ts->comp ? ((Termsavecomp*)ts)->wout : ts->w; 693 return ts->cells ? ts->w : 0;
641} 694}
642 695
696/* TODO: RESIZE reference point */
697
698void
699termpty_backscroll_adjust(Termpty *ty, int *scroll)
700{
701 Termsave *ts;
702 int y;
703 int screen_y;
704
705 if (!ty->backsize || *scroll <= 0)
706 {
707 *scroll = 0;
708 return;
709 }
710 ERR("ty->backsize:%d ty->backpos:%d *scroll:%d",
711 ty->backsize, ty->backpos, *scroll);
712 /* TODO: RESIZE have a reference point? */
713 y = ty->backsize;
714 do
715 {
716 y--;
717 ts = BACKLOG_ROW_GET(ty, y);
718 }
719 while (!ts->cells);
720 ERR("y:%d", y);
721 if (*scroll <= y)
722 return;
723 screen_y = 0;
724 while (y >= 0)
725 {
726 int nb_lines;
727
728 ts = BACKLOG_ROW_GET(ty, y);
729 assert(ts != NULL);
730
731 nb_lines = (ts->w + ty->w) / ty->w;
732 ERR("[%d] ts->w:%d ty->w:%d, nb_lines:%d",
733 y, ts->w, ty->w, nb_lines);
734 screen_y += nb_lines;
735 y--;
736 }
737
738 ERR("screen_y:%d", screen_y);
739 *scroll = screen_y;
740}
741
742
643Termcell * 743Termcell *
644termpty_cellrow_get(Termpty *ty, int y, int *wret) 744termpty_cellrow_get(Termpty *ty, int y_requested, int *wret)
645{ 745{
646 Termsave *ts, **tssrc; 746 int screen_y = 0;
747 int backlog_y = 0;
647 748
648 if (y >= 0) 749 //ERR("y_requested:%d", y_requested);
750 if (y_requested >= 0)
649 { 751 {
650 if (y >= ty->h) return NULL; 752 if (y_requested >= ty->h)
753 return NULL;
651 *wret = ty->w; 754 *wret = ty->w;
652 /* fprintf(stderr, "getting: %i (%i, %i)\n", y, ty->circular_offset, ty->h); */ 755 return &(TERMPTY_SCREEN(ty, 0, y_requested));
653 return &(TERMPTY_SCREEN(ty, 0, y));
654 } 756 }
655 if ((y < -ty->backmax) || !ty->back) return NULL; 757 if (!ty->back)
656 tssrc = &(ty->back[(ty->backmax + ty->backpos + y) % ty->backmax]); 758 return NULL;
657 ts = termpty_save_extract(*tssrc); 759
658 if (!ts) return NULL; 760 y_requested = -y_requested;
659 *tssrc = ts; 761 while (backlog_y <= ty->backsize)
660 *wret = ts->w; 762 {
661 return ts->cell; 763 Termsave *ts;
764 int nb_lines;
765
766 ts = BACKLOG_ROW_GET(ty, backlog_y);
767 if (!ts->cells)
768 {
769 //ERR("went too far: y_requested:%d screen_y:%d backlog_y:%d",
770 // y_requested, screen_y, backlog_y);
771 return NULL;
772 }
773 nb_lines = (ts->w + ty->w) / ty->w;
774
775 /* TODO: uncompress */
776 /* TODO: optimize */
777
778 //ERR("y_requested:%d screen_y:%d nb_lines:%d backlog_y:%d",
779 // y_requested, screen_y, nb_lines, backlog_y);
780 if (screen_y + nb_lines >= y_requested)
781 {
782 int delta = screen_y + nb_lines - y_requested;
783 *wret = ts->w - delta * ty->w;
784 if (*wret > ts->w)
785 *wret = ts->w;
786 return &ts->cells[delta * ty->w];
787 }
788 screen_y += nb_lines;
789 backlog_y++;
790 }
791 return NULL;
662} 792}
663 793
664void 794void
665termpty_write(Termpty *ty, const char *input, int len) 795termpty_write(Termpty *ty, const char *input, int len)
666{ 796{
@@ -670,170 +800,113 @@ termpty_write(Termpty *ty, const char *input, int len)
670 ty->fd, strerror(errno)); 800 ty->fd, strerror(errno));
671} 801}
672 802
673static int 803struct screen_info
674termpty_line_find_top(Termpty *ty, int y_end, int *top)
675{ 804{
676 int y_start = y_end; 805 Termcell *screen;
806 int w;
807 int h;
808 int x;
809 int y;
810 int cy;
811 int cx;
812 int circular_offset;
813};
814
815#define SCREEN_INFO_GET_CELLS(Tsi, X, Y) \
816 Tsi->screen[X + (((Y + Tsi->circular_offset) % Tsi->h) * Tsi->w)]
677 817
678 while (y_start > 0) 818static void
679 { 819_check_screen_info(Termpty *ty, struct screen_info *si)
680 if (TERMPTY_SCREEN(ty, ty->w - 1, y_start - 1).att.autowrapped) 820{
681 y_start--; 821 if (si->y >= si->h)
682 else
683 {
684 *top = y_start;
685 return 0;
686 }
687 }
688 while (-y_start < ty->backscroll_num)
689 { 822 {
690 Termsave *ts = ty->back[(y_start + ty->backpos - 1 + 823 Termcell *cells = &SCREEN_INFO_GET_CELLS(si, 0, 0);
691 ty->backmax) % ty->backmax]; 824
692 if (ts) 825 ERR("adjusting");
693 { 826
694 ts = termpty_save_extract(ts); 827 si->y--;
695 } 828 termpty_text_save_top(ty, cells, si->w);
696 if (!ts) 829 termpty_cells_clear(ty, cells, si->w);
697 return -1; 830
698 ty->back[(y_start + ty->backpos - 1 + ty->backmax) % ty->backmax] = ts; 831 si->circular_offset++;
699 if (ts->cell[ts->w - 1].att.autowrapped) 832 if (si->circular_offset >= si->h)
700 y_start--; 833 si->circular_offset = 0;
701 else 834
702 { 835 si->cy--;
703 *top = y_start;
704 return 0;
705 }
706 } 836 }
707 *top = y_start;
708 return 0;
709} 837}
710 838
711static int 839static void
712termpty_line_rewrap(Termpty *ty, int y_start, int y_end, 840_termpty_line_rewrap(Termpty *ty, Termcell *cells, int len,
713 Termcell *new_screen, Termsave **new_back, 841 struct screen_info *si,
714 int new_w, int new_y_end, int *new_y_startp, 842 Eina_Bool set_cursor)
715 int *new_cyp)
716{ 843{
717 /* variables prefixed by new_ are about the resized term being built up */ 844 int autowrapped = cells[len-1].att.autowrapped;
718 int x, y, new_x, new_y, new_y_start;
719 int len, len_last, len_remaining, copy_width, new_ts_width;
720 Termsave *ts, *new_ts;
721 Termcell *line, *new_line = NULL;
722 845
723 if (y_end >= 0) 846 ERR("si->x:%d si->y:%d si->cx:%d si->cy:%d",
847 si->x, si->y, si->cx, si->cy);
848 if (len == 0)
724 { 849 {
725 len_last = termpty_line_length(&TERMPTY_SCREEN(ty, 0, y_end), ty->w); 850 if (set_cursor)
726 }
727 else
728 {
729 ts = termpty_save_extract(ty->back[(y_end + ty->backpos +
730 ty->backmax) % ty->backmax]);
731 if (!ts)
732 return -1;
733 ty->back[(y_end + ty->backpos + ty->backmax) % ty->backmax] = ts;
734 len_last = ts->w;
735 }
736 len_remaining = len_last + (y_end - y_start) * ty->w;
737 new_y_start = new_y_end;
738 if (len_remaining)
739 {
740 new_y_start -= (len_remaining + new_w - 1) / new_w - 1;
741 }
742 else
743 {
744 if (new_y_start < 0)
745 new_back[new_y_start + ty->backmax] = termpty_save_new(0);
746 *new_y_startp = new_y_start;
747 return 0;
748 }
749 if (-new_y_start > ty->backmax)
750 {
751 y_start += ((-new_y_start - ty->backmax) * new_w) / ty->w;
752 x = ((-new_y_start - ty->backmax) * new_w) % ty->w;
753 len_remaining -= (-new_y_start - ty->backmax) * new_w;
754 new_y_start = -ty->backmax;
755 }
756 else
757 {
758 x = 0;
759 }
760 y = y_start;
761 new_x = 0;
762 new_y = new_y_start;
763
764 while (y <= y_end)
765 {
766 if (y >= 0)
767 { 851 {
768 line = &TERMPTY_SCREEN(ty, 0, y); 852 si->cy = si->y;
853 si->cx = 0;
769 } 854 }
770 else 855 si->y++;
771 { 856 si->x = 0;
772 ts = termpty_save_extract(ty->back[(y + ty->backpos + 857 _check_screen_info(ty, si);
773 ty->backmax) % ty->backmax]); 858 return;
774 if (!ts) 859 }
775 return -1; 860 while (len > 0)
776 ty->back[(y + ty->backpos + ty->backmax) % ty->backmax] = ts; 861 {
777 line = ts->cell; 862 int copy_width = MIN(len, si->w - si->x);
778 } 863
779 if (y == y_end) 864 ERR("len:%d copy_width:%d", len, copy_width);
780 len = len_last; 865 termpty_cell_copy(ty,
781 else 866 /*src*/ cells,
782 len = ty->w; 867 /*dst*/&SCREEN_INFO_GET_CELLS(si, si->x, si->y),
783 line[len - 1].att.autowrapped = 0; 868 copy_width);
784 while (x < len) 869 if (set_cursor)
785 { 870 {
786 copy_width = MIN(len - x, new_w - new_x); 871 if (ty->cursor_state.cx <= copy_width)
787 if (new_x == 0)
788 { 872 {
789 if (new_y >= 0) 873 si->cx = ty->cursor_state.cx;
790 { 874 si->cy = si->y;
791 new_line = new_screen + (new_y * new_w);
792 }
793 else
794 {
795 new_ts_width = MIN(len_remaining, new_w);
796 new_ts = termpty_save_new(new_ts_width);
797 if (!new_ts)
798 return -1;
799 new_line = new_ts->cell;
800 new_back[new_y + ty->backmax] = new_ts;
801 }
802 }
803 if (y == ty->cursor_state.cy)
804 {
805 *new_cyp = new_y_start;
806 } 875 }
807 if (new_line) 876 else
808 { 877 {
809 termpty_cell_copy(ty, line + x, new_line + new_x, copy_width); 878 ty->cursor_state.cx -= copy_width;
810 x += copy_width;
811 new_x += copy_width;
812 len_remaining -= copy_width;
813 if ((new_x == new_w) && (new_y != new_y_end))
814 {
815 new_line[new_x - 1].att.autowrapped = 1;
816 new_x = 0;
817 new_y++;
818 }
819 } 879 }
820 } 880 }
821 x = 0; 881 len -= copy_width;
822 y++; 882 si->x += copy_width;
883 ERR("si->x:%d si->w:%d", si->x, si->w);
884 if (si->x >= si->w)
885 {
886 si->y++;
887 si->x = 0;
888 }
889 _check_screen_info(ty, si);
890 }
891 ERR("autowrapped:%d", autowrapped);
892 if (!autowrapped)
893 {
894 si->y++;
895 si->x = 0;
896 _check_screen_info(ty, si);
823 } 897 }
824 *new_y_startp = new_y_start;
825 return 0;
826} 898}
827 899
828
829void 900void
830termpty_resize(Termpty *ty, int new_w, int new_h) 901termpty_resize(Termpty *ty, int new_w, int new_h)
831{ 902{
832 Termcell *new_screen = NULL; 903 Termcell *new_screen = NULL;
833 Termsave **new_back = NULL; 904 int old_y = 0,
834 int y_start = 0, y_end = 0, new_y_start = 0, new_y_end, 905 old_w = ty->w,
835 new_cy = ty->cursor_state.cy; 906 old_h = ty->h,
836 int i, altbuf = 0; 907 effective_old_h;
908 int altbuf = 0;
909 struct screen_info new_si = {.screen = NULL};
837 910
838 if ((ty->w == new_w) && (ty->h == new_h)) return; 911 if ((ty->w == new_w) && (ty->h == new_h)) return;
839 if ((new_w == new_h) && (new_w == 1)) return; // FIXME: something weird is 912 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)
854 ty->screen2 = calloc(1, sizeof(Termcell) * new_w * new_h); 927 ty->screen2 = calloc(1, sizeof(Termcell) * new_w * new_h);
855 if (!ty->screen2) 928 if (!ty->screen2)
856 goto bad; 929 goto bad;
857 new_back = calloc(sizeof(Termsave *), ty->backmax);
858 930
859 y_end = ty->cursor_state.cy; 931 new_si.screen = new_screen;
860 new_y_end = new_h - 1; 932 new_si.w = new_w;
861 /* For each "full line" in old buffers, rewrap. 933 new_si.h = new_h;
862 * From most recent to oldest */ 934
863 while ((y_end >= -ty->backscroll_num) && (new_y_end >= -ty->backmax)) 935 /* compute the effective height on the old screen */
936 effective_old_h = old_h;
937 for (old_y = old_h -1; old_y >= 0; old_y--)
864 { 938 {
865 if (termpty_line_find_top(ty, y_end, &y_start) < 0) 939 Termcell *cells = &TERMPTY_SCREEN(ty, 0, old_y);
866 goto bad; 940 if (!termpty_line_is_empty(cells, old_w))
867 if (termpty_line_rewrap(ty, y_start, y_end, 941 {
868 new_screen, new_back, 942 effective_old_h = old_y + 1;
869 new_w, new_y_end, 943 break;
870 &new_y_start, &new_cy) < 0) 944 }
871 goto bad; 945 }
872 946
873 y_end = y_start - 1; 947 for (old_y = 0; old_y < effective_old_h; old_y++)
874 new_y_end = new_y_start - 1; 948 {
949 /* for each line in the old screen, append it to the new screen */
950 Termcell *cells = &TERMPTY_SCREEN(ty, 0, old_y);
951 int len;
952
953 len = termpty_line_length(cells, old_w);
954 ERR("[%d] len:%d", old_y, len);
955 _termpty_line_rewrap(ty, cells, len, &new_si,
956 old_y == ty->cursor_state.cy);
875 } 957 }
876 958
877 free(ty->screen); 959 free(ty->screen);
878 ty->screen = new_screen; 960 ty->screen = new_screen;
879 for (i = 1; i <= ty->backscroll_num; i++) 961
880 termpty_save_free(ty->back[(ty->backpos - i + ty->backmax) % ty->backmax]); 962 ty->cursor_state.cy = (new_si.cy >= 0) ? new_si.cy : 0;
881 free(ty->back); 963 ty->cursor_state.cx = (new_si.cx >= 0) ? new_si.cx : 0;
882 ty->back = new_back; 964 ty->circular_offset = new_si.circular_offset;
883 965
884 ty->w = new_w; 966 ty->w = new_w;
885 ty->h = new_h; 967 ty->h = new_h;
886 ty->circular_offset = MAX(new_y_start, 0);
887 ty->backpos = 0;
888 ty->backscroll_num = MAX(-new_y_start, 0);
889 ty->termstate.had_cr = 0; 968 ty->termstate.had_cr = 0;
890 969 ty->termstate.wrapnext = 0;
891 ty->cursor_state.cy = (new_cy + new_h - ty->circular_offset) % new_h;
892 970
893 if (altbuf) 971 if (altbuf)
894 termpty_screen_swap(ty); 972 termpty_screen_swap(ty);
895 973
896 ty->termstate.wrapnext = 0;
897
898 _limit_coord(ty); 974 _limit_coord(ty);
899 975
900 _pty_size(ty); 976 _pty_size(ty);
@@ -905,8 +981,6 @@ termpty_resize(Termpty *ty, int new_w, int new_h)
905bad: 981bad:
906 termpty_save_thaw(); 982 termpty_save_thaw();
907 free(new_screen); 983 free(new_screen);
908 free(new_back);
909
910} 984}
911 985
912void 986void
@@ -914,25 +988,24 @@ termpty_backscroll_set(Termpty *ty, int size)
914{ 988{
915 int i; 989 int i;
916 990
917 if (ty->backmax == size) return; 991 if (ty->backsize == size)
918 992 return;
993
994 /* TODO: RESIZE: handle that case better: changing backscroll size */
919 termpty_save_freeze(); 995 termpty_save_freeze();
920 996
921 if (ty->back) 997 if (ty->back)
922 { 998 {
923 for (i = 0; i < ty->backmax; i++) 999 for (i = 0; i < ty->backsize; i++)
924 { 1000 termpty_save_free(&ty->back[i]);
925 if (ty->back[i]) termpty_save_free(ty->back[i]);
926 }
927 free(ty->back); 1001 free(ty->back);
928 } 1002 }
929 if (size > 0) 1003 if (size > 0)
930 ty->back = calloc(1, sizeof(Termsave *) * size); 1004 ty->back = calloc(1, sizeof(Termsave) * size);
931 else 1005 else
932 ty->back = NULL; 1006 ty->back = NULL;
933 ty->backscroll_num = 0;
934 ty->backpos = 0; 1007 ty->backpos = 0;
935 ty->backmax = size; 1008 ty->backsize = size;
936 termpty_save_thaw(); 1009 termpty_save_thaw();
937} 1010}
938 1011
@@ -1089,7 +1162,7 @@ void
1089termpty_cell_copy(Termpty *ty, Termcell *src, Termcell *dst, int n) 1162termpty_cell_copy(Termpty *ty, Termcell *src, Termcell *dst, int n)
1090{ 1163{
1091 int i; 1164 int i;
1092 1165
1093 for (i = 0; i < n; i++) 1166 for (i = 0; i < n; i++)
1094 { 1167 {
1095 _handle_block_codepoint_overwrite(ty, dst[i].codepoint, src[i].codepoint); 1168 _handle_block_codepoint_overwrite(ty, dst[i].codepoint, src[i].codepoint);
diff --git a/src/bin/termpty.h b/src/bin/termpty.h
index 7aba97a..26c5de0 100644
--- a/src/bin/termpty.h
+++ b/src/bin/termpty.h
@@ -99,7 +99,7 @@ struct _Termpty
99 } prop; 99 } prop;
100 const char *cur_cmd; 100 const char *cur_cmd;
101 Termcell *screen, *screen2; 101 Termcell *screen, *screen2;
102 Termsave **back; 102 Termsave *back;
103 unsigned char oldbuf[4]; 103 unsigned char oldbuf[4];
104 Eina_Unicode *buf; 104 Eina_Unicode *buf;
105 size_t buflen; 105 size_t buflen;
@@ -107,8 +107,7 @@ struct _Termpty
107 int fd, slavefd; 107 int fd, slavefd;
108 int circular_offset; 108 int circular_offset;
109 int circular_offset2; 109 int circular_offset2;
110 int backmax, backpos; 110 int backsize, backpos;
111 int backscroll_num;
112 struct { 111 struct {
113 int curid; 112 int curid;
114 Eina_Hash *blocks; 113 Eina_Hash *blocks;
@@ -178,9 +177,11 @@ struct _Termsave
178 unsigned int comp : 1; 177 unsigned int comp : 1;
179 unsigned int z : 1; 178 unsigned int z : 1;
180 unsigned int w : 22; 179 unsigned int w : 22;
181 Termcell cell[1]; 180 /* TODO: union ? */
181 Termcell *cells;
182}; 182};
183 183
184/* TODO: RESIZE rewrite Termsavecomp */
184struct _Termsavecomp 185struct _Termsavecomp
185{ 186{
186 unsigned int gen : 8; 187 unsigned int gen : 8;
@@ -232,8 +233,9 @@ void termpty_cellcomp_thaw(Termpty *ty);
232Termcell *termpty_cellrow_get(Termpty *ty, int y, int *wret); 233Termcell *termpty_cellrow_get(Termpty *ty, int y, int *wret);
233ssize_t termpty_row_length(Termpty *ty, int y); 234ssize_t termpty_row_length(Termpty *ty, int y);
234void termpty_write(Termpty *ty, const char *input, int len); 235void termpty_write(Termpty *ty, const char *input, int len);
235void termpty_resize(Termpty *ty, int w, int h); 236void termpty_resize(Termpty *ty, int new_w, int new_h);
236void termpty_backscroll_set(Termpty *ty, int size); 237void termpty_backscroll_set(Termpty *ty, int size);
238void termpty_backscroll_adjust(Termpty *ty, int *scroll);
237 239
238pid_t termpty_pid_get(const Termpty *ty); 240pid_t termpty_pid_get(const Termpty *ty);
239void termpty_block_free(Termblock *tb); 241void termpty_block_free(Termblock *tb);
diff --git a/src/bin/termptyops.c b/src/bin/termptyops.c
index f4ef69d..0df51f8 100644
--- a/src/bin/termptyops.c
+++ b/src/bin/termptyops.c
@@ -33,34 +33,6 @@ termpty_cells_clear(Termpty *ty, Termcell *cells, int count)
33} 33}
34 34
35void 35void
36termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
37{
38 Termsave *ts;
39 ssize_t w;
40
41 if (ty->backmax <= 0) return;
42
43 termpty_save_freeze();
44 w = termpty_line_length(cells, w_max);
45 ts = termpty_save_new(w);
46 if (!ts)
47 return;
48 termpty_cell_copy(ty, cells, ts->cell, w);
49 if (!ty->back) ty->back = calloc(1, sizeof(Termsave *) * ty->backmax);
50 if (ty->back[ty->backpos])
51 {
52 termpty_save_free(ty->back[ty->backpos]);
53 ty->back[ty->backpos] = NULL;
54 }
55 ty->back[ty->backpos] = ts;
56 ty->backpos++;
57 if (ty->backpos >= ty->backmax) ty->backpos = 0;
58 ty->backscroll_num++;
59 if (ty->backscroll_num >= ty->backmax) ty->backscroll_num = ty->backmax;
60 termpty_save_thaw();
61}
62
63void
64termpty_text_scroll(Termpty *ty, Eina_Bool clear) 36termpty_text_scroll(Termpty *ty, Eina_Bool clear)
65{ 37{
66 Termcell *cells = NULL, *cells2; 38 Termcell *cells = NULL, *cells2;
@@ -377,6 +349,8 @@ termpty_reset_att(Termatt *att)
377void 349void
378termpty_reset_state(Termpty *ty) 350termpty_reset_state(Termpty *ty)
379{ 351{
352 int backsize;
353
380 ty->cursor_state.cx = 0; 354 ty->cursor_state.cx = 0;
381 ty->cursor_state.cy = 0; 355 ty->cursor_state.cy = 0;
382 ty->termstate.scroll_y1 = 0; 356 ty->termstate.scroll_y1 = 0;
@@ -411,17 +385,15 @@ termpty_reset_state(Termpty *ty)
411 if (ty->back) 385 if (ty->back)
412 { 386 {
413 int i; 387 int i;
414 for (i = 0; i < ty->backmax; i++) 388 for (i = 0; i < ty->backsize; i++)
415 { 389 termpty_save_free(&ty->back[i]);
416 if (ty->back[i]) termpty_save_free(ty->back[i]);
417 }
418 free(ty->back); 390 free(ty->back);
419 ty->back = NULL; 391 ty->back = NULL;
420 } 392 }
421 ty->backscroll_num = 0;
422 ty->backpos = 0; 393 ty->backpos = 0;
423 if (ty->backmax) 394 backsize = ty->backsize;
424 ty->back = calloc(1, sizeof(Termsave *) * ty->backmax); 395 ty->backsize = 0;
396 termpty_backscroll_set(ty, backsize);
425 termpty_save_thaw(); 397 termpty_save_thaw();
426} 398}
427 399
diff --git a/src/bin/termptysave.c b/src/bin/termptysave.c
index 2c22200..3c5f1b7 100644
--- a/src/bin/termptysave.c
+++ b/src/bin/termptysave.c
@@ -27,10 +27,13 @@ struct _Alloc
27 unsigned char __pad; 27 unsigned char __pad;
28}; 28};
29 29
30#if 0
30static uint64_t _allocated = 0; 31static uint64_t _allocated = 0;
32#endif
31static unsigned char cur_gen = 0; 33static unsigned char cur_gen = 0;
32static Alloc *alloc[MEM_BLOCKS] = { 0 }; 34static Alloc *alloc[MEM_BLOCKS] = { 0 };
33 35
36#if 0
34static int 37static int
35roundup_block_size(int sz) 38roundup_block_size(int sz)
36{ 39{
@@ -122,21 +125,25 @@ _alloc_new(int size, unsigned char gen)
122 ptr += sizeof(Alloc); 125 ptr += sizeof(Alloc);
123 return ptr; 126 return ptr;
124} 127}
128#endif
125 129
126static void * 130static void *
127_ts_new(int size) 131_ts_new(int size)
128{ 132{
129 void *ptr; 133 /* TODO: RESIZE rewrite that stuff */
134 //void *ptr;
130 135
131 if (!size) return NULL; 136 if (!size) return NULL;
132 ptr = _alloc_new(size, cur_gen); 137 //ptr = _alloc_new(size, cur_gen);
133 138
134 return ptr; 139 return calloc(1, size);
135} 140}
136 141
137static void 142static void
138_ts_free(void *ptr) 143_ts_free(void *ptr)
139{ 144{
145 free(ptr);
146#if 0
140 Alloc *al; 147 Alloc *al;
141 unsigned int sz; 148 unsigned int sz;
142 Termsavecomp *ts = ptr; 149 Termsavecomp *ts = ptr;
@@ -165,6 +172,7 @@ _ts_free(void *ptr)
165#else 172#else
166 munmap(al, al->size); 173 munmap(al, al->size);
167#endif 174#endif
175#endif
168} 176}
169 177
170static void 178static void
@@ -210,12 +218,15 @@ static Eina_List *ptys = NULL;
210static Ecore_Idler *idler = NULL; 218static Ecore_Idler *idler = NULL;
211static Ecore_Timer *timer = NULL; 219static Ecore_Timer *timer = NULL;
212 220
221#if 0
213static Termsave * 222static Termsave *
214_save_comp(Termsave *ts) 223_save_comp(Termsave *ts)
215{ 224{
216 Termsave *ts2; 225 Termsave *ts2;
217 Termsavecomp *tsc; 226 Termsavecomp *tsc;
218 227
228 ERR("save comp");
229
219 // already compacted 230 // already compacted
220 if (ts->comp) return ts; 231 if (ts->comp) return ts;
221 // make new allocation for new generation 232 // make new allocation for new generation
@@ -226,7 +237,7 @@ _save_comp(Termsave *ts)
226 char *buf; 237 char *buf;
227 238
228 buf = alloca(LZ4_compressBound(ts->w * sizeof(Termcell))); 239 buf = alloca(LZ4_compressBound(ts->w * sizeof(Termcell)));
229 bytes = LZ4_compress((char *)(&(ts->cell[0])), buf, 240 bytes = LZ4_compress((char *)(&(ts->cells[0])), buf,
230 ts->w * sizeof(Termcell)); 241 ts->w * sizeof(Termcell));
231 tsc = _ts_new(sizeof(Termsavecomp) + bytes); 242 tsc = _ts_new(sizeof(Termsavecomp) + bytes);
232 if (!tsc) 243 if (!tsc)
@@ -262,6 +273,7 @@ done:
262 ts_compfreeze--; 273 ts_compfreeze--;
263 return ts2; 274 return ts2;
264} 275}
276#endif
265 277
266static void 278static void
267_walk_pty(Termpty *ty) 279_walk_pty(Termpty *ty)
@@ -270,18 +282,20 @@ _walk_pty(Termpty *ty)
270// int c0 = 0, c1 = 0; 282// int c0 = 0, c1 = 0;
271 283
272 if (!ty->back) return; 284 if (!ty->back) return;
273 for (i = 0; i < ty->backmax; i++) 285 for (i = 0; i < ty->backsize; i++)
274 { 286 {
275 Termsavecomp *tsc = (Termsavecomp *)ty->back[i]; 287 Termsavecomp *tsc = (Termsavecomp *)&ty->back[i];
276 288
277 if (tsc) 289 if (tsc)
278 { 290 {
279 ty->back[i] = _save_comp(ty->back[i]); 291#if 0
292 ty->back[i] = _save_comp(tsc);
280 tsc = (Termsavecomp *)ty->back[i]; 293 tsc = (Termsavecomp *)ty->back[i];
281 if (tsc->comp) ts_comp++; 294 if (tsc->comp) ts_comp++;
282 else ts_uncomp++; 295 else ts_uncomp++;
283// c0 += tsc->w; 296// c0 += tsc->w;
284// c1 += tsc->wout * sizeof(Termcell); 297// c1 += tsc->wout * sizeof(Termcell);
298#endif
285 } 299 }
286 } 300 }
287// printf("compress ratio: %1.3f\n", (double)c0 / (double)c1); 301// printf("compress ratio: %1.3f\n", (double)c0 / (double)c1);
@@ -290,10 +304,14 @@ _walk_pty(Termpty *ty)
290static Eina_Bool 304static Eina_Bool
291_idler(void *data EINA_UNUSED) 305_idler(void *data EINA_UNUSED)
292{ 306{
307 /* TODO: RESIZE : re-enable compression */
308 return EINA_FALSE;
309
293 Eina_List *l; 310 Eina_List *l;
294 Termpty *ty; 311 Termpty *ty;
295// double t0, t; 312// double t0, t;
296 313
314
297 _mem_gen_next(); 315 _mem_gen_next();
298 316
299// t0 = ecore_time_get(); 317// t0 = ecore_time_get();
@@ -326,6 +344,8 @@ _timer(void *data EINA_UNUSED)
326static inline void 344static inline void
327_check_compressor(Eina_Bool frozen) 345_check_compressor(Eina_Bool frozen)
328{ 346{
347 /* TODO: RESIZE re-enable compressor */
348 return;
329 if (freeze) return; 349 if (freeze) return;
330 if (idler) return; 350 if (idler) return;
331 if ((ts_uncomp > 256) || (ts_freeops > 256)) 351 if ((ts_uncomp > 256) || (ts_freeops > 256))
@@ -395,11 +415,11 @@ termpty_save_extract(Termsave *ts)
395 ts2->gen = _mem_gen_get(); 415 ts2->gen = _mem_gen_get();
396 ts2->w = tsc->wout; 416 ts2->w = tsc->wout;
397 buf = ((char *)tsc) + sizeof(Termsavecomp); 417 buf = ((char *)tsc) + sizeof(Termsavecomp);
398 bytes = LZ4_uncompress(buf, (char *)(&(ts2->cell[0])), 418 bytes = LZ4_uncompress(buf, (char *)(&(ts2->cells[0])),
399 tsc->wout * sizeof(Termcell)); 419 tsc->wout * sizeof(Termcell));
400 if (bytes < 0) 420 if (bytes < 0)
401 { 421 {
402 memset(&(ts2->cell[0]), 0, tsc->wout * sizeof(Termcell)); 422 memset(&(ts2->cells[0]), 0, tsc->wout * sizeof(Termcell));
403// ERR("Decompress problem in row at byte %i", -bytes); 423// ERR("Decompress problem in row at byte %i", -bytes);
404 } 424 }
405 if (ts->comp) ts_comp--; 425 if (ts->comp) ts_comp--;
@@ -417,10 +437,13 @@ termpty_save_extract(Termsave *ts)
417} 437}
418 438
419Termsave * 439Termsave *
420termpty_save_new(int w) 440termpty_save_new(Termsave *ts, int w)
421{ 441{
422 Termsave *ts = _ts_new(sizeof(Termsave) + ((w - 1) * sizeof(Termcell))); 442 termpty_save_free(ts);
423 if (!ts) return NULL; 443
444 Termcell *cells = calloc(1, w * sizeof(Termcell));
445 if (!cells ) return NULL;
446 ts->cells = cells;
424 ts->gen = _mem_gen_get(); 447 ts->gen = _mem_gen_get();
425 ts->w = w; 448 ts->w = w;
426 if (!ts_compfreeze) ts_uncomp++; 449 if (!ts_compfreeze) ts_uncomp++;
@@ -428,6 +451,21 @@ termpty_save_new(int w)
428 return ts; 451 return ts;
429} 452}
430 453
454Termsave *
455termpty_save_expand(Termsave *ts, Termcell *cells, ssize_t delta)
456{
457 Termcell *newcells;
458
459 newcells = realloc(ts->cells, (ts->w + delta) * sizeof(Termcell));
460 if (!newcells)
461 return NULL;
462 newcells[ts->w - 1].att.autowrapped = 0;
463 memcpy(&newcells[ts->w], cells, delta * sizeof(Termcell));
464 ts->w += delta;
465 ts->cells = newcells;
466 return ts;
467}
468
431void 469void
432termpty_save_free(Termsave *ts) 470termpty_save_free(Termsave *ts)
433{ 471{
@@ -438,6 +476,8 @@ termpty_save_free(Termsave *ts)
438 else ts_uncomp--; 476 else ts_uncomp--;
439 ts_freeops++; 477 ts_freeops++;
440 } 478 }
441 _ts_free(ts); 479 _ts_free(ts->cells);
480 ts->cells = NULL;
481 ts->w = 0;
442 _check_compressor(EINA_FALSE); 482 _check_compressor(EINA_FALSE);
443} 483}
diff --git a/src/bin/termptysave.h b/src/bin/termptysave.h
index ce430a5..4520fcc 100644
--- a/src/bin/termptysave.h
+++ b/src/bin/termptysave.h
@@ -6,7 +6,8 @@ void termpty_save_thaw(void);
6void termpty_save_register(Termpty *ty); 6void termpty_save_register(Termpty *ty);
7void termpty_save_unregister(Termpty *ty); 7void termpty_save_unregister(Termpty *ty);
8Termsave *termpty_save_extract(Termsave *ts); 8Termsave *termpty_save_extract(Termsave *ts);
9Termsave *termpty_save_new(int w); 9Termsave *termpty_save_new(Termsave *ts, int w);
10void termpty_save_free(Termsave *ts); 10void termpty_save_free(Termsave *ts);
11Termsave *termpty_save_expand(Termsave *ts, Termcell *cells, ssize_t delta);
11 12
12#endif 13#endif