summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2015-06-02 22:48:50 +0200
committerBoris Faure <billiob@gmail.com>2015-06-02 22:48:50 +0200
commit1f3f779258c86b170edb3e634548a446fe5c9b58 (patch)
tree26d4f94a547cb2cb3f732faa13b2faeb40e7609a /src
parentc86b35309cf2cad82875dfc213ce3a398f8ec92d (diff)
ensure cursor coordinates are always valid
Diffstat (limited to 'src')
-rw-r--r--src/bin/termpty.c28
-rw-r--r--src/bin/termpty.h8
-rw-r--r--src/bin/termptyesc.c46
-rw-r--r--src/bin/termptyops.c13
4 files changed, 58 insertions, 37 deletions
diff --git a/src/bin/termpty.c b/src/bin/termpty.c
index c9b8b7d..5e49ba4 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -270,21 +270,14 @@ _cb_fd_read(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
270static void 270static void
271_limit_coord(Termpty *ty) 271_limit_coord(Termpty *ty)
272{ 272{
273 ty->termstate.wrapnext = 0; 273 TERMPTY_RESTRICT_FIELD(ty->termstate.had_cr_x, 0, ty->w);
274 if (ty->termstate.had_cr_x >= ty->w) 274 TERMPTY_RESTRICT_FIELD(ty->termstate.had_cr_y, 0, ty->h);
275 ty->termstate.had_cr_x = ty->w - 1; 275
276 if (ty->termstate.had_cr_y >= ty->h) 276 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
277 ty->termstate.had_cr_y = ty->h - 1; 277 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
278 278
279 if (ty->cursor_state.cx >= ty->w) 279 TERMPTY_RESTRICT_FIELD(ty->cursor_save.cx, 0, ty->w);
280 ty->cursor_state.cx = ty->w - 1; 280 TERMPTY_RESTRICT_FIELD(ty->cursor_save.cy, 0, ty->h);
281 if (ty->cursor_state.cy >= ty->h)
282 ty->cursor_state.cy = ty->h - 1;
283
284 if (ty->cursor_save.cx >= ty->w)
285 ty->cursor_save.cx = ty->w - 1;
286 if (ty->cursor_save.cy >= ty->h)
287 ty->cursor_save.cy = ty->h - 1;
288} 281}
289 282
290Termpty * 283Termpty *
@@ -897,7 +890,10 @@ termpty_resize(Termpty *ty, int new_w, int new_h)
897 890
898 ty->cursor_state.cy = (new_cy + new_h - ty->circular_offset) % new_h; 891 ty->cursor_state.cy = (new_cy + new_h - ty->circular_offset) % new_h;
899 892
900 if (altbuf) termpty_screen_swap(ty); 893 if (altbuf)
894 termpty_screen_swap(ty);
895
896 ty->termstate.wrapnext = 0;
901 897
902 _limit_coord(ty); 898 _limit_coord(ty);
903 899
diff --git a/src/bin/termpty.h b/src/bin/termpty.h
index d5aad70..7aba97a 100644
--- a/src/bin/termpty.h
+++ b/src/bin/termpty.h
@@ -260,4 +260,12 @@ extern int _termpty_log_dom;
260#define TERMPTY_FMTCLR(Tatt) \ 260#define TERMPTY_FMTCLR(Tatt) \
261 (Tatt).autowrapped = (Tatt).newline = (Tatt).tab = 0 261 (Tatt).autowrapped = (Tatt).newline = (Tatt).tab = 0
262 262
263#define TERMPTY_RESTRICT_FIELD(Field, Min, Max) \
264 do { \
265 if (Field >= Max) \
266 Field = Max - 1; \
267 else if (Field < Min) \
268 Field = Min; \
269 } while (0)
270
263#endif 271#endif
diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c
index 14dbbb7..6de1340 100644
--- a/src/bin/termptyesc.c
+++ b/src/bin/termptyesc.c
@@ -66,7 +66,7 @@ _handle_cursor_control(Termpty *ty, const Eina_Unicode *cc)
66 ty->termstate.had_cr = 0; 66 ty->termstate.had_cr = 0;
67 ty->termstate.wrapnext = 0; 67 ty->termstate.wrapnext = 0;
68 ty->cursor_state.cx--; 68 ty->cursor_state.cx--;
69 if (ty->cursor_state.cx < 0) ty->cursor_state.cx = 0; 69 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
70 return; 70 return;
71 case 0x09: // HT '\t' (horizontal tab) 71 case 0x09: // HT '\t' (horizontal tab)
72 DBG("->HT"); 72 DBG("->HT");
@@ -75,8 +75,7 @@ _handle_cursor_control(Termpty *ty, const Eina_Unicode *cc)
75 ty->termstate.wrapnext = 0; 75 ty->termstate.wrapnext = 0;
76 ty->cursor_state.cx += 8; 76 ty->cursor_state.cx += 8;
77 ty->cursor_state.cx = (ty->cursor_state.cx / 8) * 8; 77 ty->cursor_state.cx = (ty->cursor_state.cx / 8) * 8;
78 if (ty->cursor_state.cx >= ty->w) 78 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
79 ty->cursor_state.cx = ty->w - 1;
80 return; 79 return;
81 case 0x0a: // LF '\n' (new line) 80 case 0x0a: // LF '\n' (new line)
82 case 0x0b: // VT '\v' (vertical tab) 81 case 0x0b: // VT '\v' (vertical tab)
@@ -91,6 +90,7 @@ _handle_cursor_control(Termpty *ty, const Eina_Unicode *cc)
91 ty->termstate.wrapnext = 0; 90 ty->termstate.wrapnext = 0;
92 if (ty->termstate.crlf) ty->cursor_state.cx = 0; 91 if (ty->termstate.crlf) ty->cursor_state.cx = 0;
93 ty->cursor_state.cy++; 92 ty->cursor_state.cy++;
93 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
94 termpty_text_scroll_test(ty, EINA_TRUE); 94 termpty_text_scroll_test(ty, EINA_TRUE);
95 return; 95 return;
96 case 0x0d: // CR '\r' (carriage ret) 96 case 0x0d: // CR '\r' (carriage ret)
@@ -682,6 +682,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
682 termpty_text_append(ty, blank, 1); 682 termpty_text_append(ty, blank, 1);
683 ty->termstate.insert = pi; 683 ty->termstate.insert = pi;
684 ty->cursor_state.cx = cx; 684 ty->cursor_state.cx = cx;
685 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
685 } 686 }
686 break; 687 break;
687 case 'A': // cursor up N 688 case 'A': // cursor up N
@@ -691,6 +692,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
691 DBG("cursor up %d", arg); 692 DBG("cursor up %d", arg);
692 ty->termstate.wrapnext = 0; 693 ty->termstate.wrapnext = 0;
693 ty->cursor_state.cy = MAX(0, ty->cursor_state.cy - arg); 694 ty->cursor_state.cy = MAX(0, ty->cursor_state.cy - arg);
695 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
694 break; 696 break;
695 case 'B': // cursor down N 697 case 'B': // cursor down N
696 arg = _csi_arg_get(&b); 698 arg = _csi_arg_get(&b);
@@ -698,6 +700,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
698 DBG("cursor down %d", arg); 700 DBG("cursor down %d", arg);
699 ty->termstate.wrapnext = 0; 701 ty->termstate.wrapnext = 0;
700 ty->cursor_state.cy = MIN(ty->h - 1, ty->cursor_state.cy + arg); 702 ty->cursor_state.cy = MIN(ty->h - 1, ty->cursor_state.cy + arg);
703 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
701 break; 704 break;
702 case 'D': // cursor left N 705 case 'D': // cursor left N
703 arg = _csi_arg_get(&b); 706 arg = _csi_arg_get(&b);
@@ -705,10 +708,8 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
705 DBG("cursor left %d", arg); 708 DBG("cursor left %d", arg);
706 ty->termstate.wrapnext = 0; 709 ty->termstate.wrapnext = 0;
707 for (i = 0; i < arg; i++) 710 for (i = 0; i < arg; i++)
708 { 711 ty->cursor_state.cx--;
709 ty->cursor_state.cx--; 712 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
710 if (ty->cursor_state.cx < 0) ty->cursor_state.cx = 0;
711 }
712 break; 713 break;
713 case 'C': // cursor right N 714 case 'C': // cursor right N
714 case 'a': // cursor right N 715 case 'a': // cursor right N
@@ -717,10 +718,8 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
717 DBG("cursor right %d", arg); 718 DBG("cursor right %d", arg);
718 ty->termstate.wrapnext = 0; 719 ty->termstate.wrapnext = 0;
719 for (i = 0; i < arg; i++) 720 for (i = 0; i < arg; i++)
720 { 721 ty->cursor_state.cx++;
721 ty->cursor_state.cx++; 722 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
722 if (ty->cursor_state.cx >= ty->w) ty->cursor_state.cx = ty->w - 1;
723 }
724 break; 723 break;
725 case 'H': // cursor pos set 724 case 'H': // cursor pos set
726 case 'f': // cursor pos set 725 case 'f': // cursor pos set
@@ -740,6 +739,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
740 if (b) 739 if (b)
741 { 740 {
742 ty->cursor_state.cy = arg; 741 ty->cursor_state.cy = arg;
742 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
743 arg = _csi_arg_get(&b); 743 arg = _csi_arg_get(&b);
744 if (arg < 1) arg = 1; 744 if (arg < 1) arg = 1;
745 arg--; 745 arg--;
@@ -747,9 +747,14 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
747 else arg = 0; 747 else arg = 0;
748 748
749 if (arg >= ty->w) arg = ty->w - 1; 749 if (arg >= ty->w) arg = ty->w - 1;
750 if (b) ty->cursor_state.cx = arg; 750 if (b)
751 {
752 ty->cursor_state.cx = arg;
753 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
754 }
751 } 755 }
752 ty->cursor_state.cy += ty->termstate.margin_top; 756 ty->cursor_state.cy += ty->termstate.margin_top;
757 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
753 break; 758 break;
754 case 'G': // to column N 759 case 'G': // to column N
755 arg = _csi_arg_get(&b); 760 arg = _csi_arg_get(&b);
@@ -757,8 +762,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
757 DBG("to column %d", arg); 762 DBG("to column %d", arg);
758 ty->termstate.wrapnext = 0; 763 ty->termstate.wrapnext = 0;
759 ty->cursor_state.cx = arg - 1; 764 ty->cursor_state.cx = arg - 1;
760 if (ty->cursor_state.cx < 0) ty->cursor_state.cx = 0; 765 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
761 else if (ty->cursor_state.cx >= ty->w) ty->cursor_state.cx = ty->w - 1;
762 break; 766 break;
763 case 'd': // to row N 767 case 'd': // to row N
764 arg = _csi_arg_get(&b); 768 arg = _csi_arg_get(&b);
@@ -766,8 +770,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
766 DBG("to row %d", arg); 770 DBG("to row %d", arg);
767 ty->termstate.wrapnext = 0; 771 ty->termstate.wrapnext = 0;
768 ty->cursor_state.cy = arg - 1; 772 ty->cursor_state.cy = arg - 1;
769 if (ty->cursor_state.cy < 0) ty->cursor_state.cy = 0; 773 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
770 else if (ty->cursor_state.cy >= ty->h) ty->cursor_state.cy = ty->h - 1;
771 break; 774 break;
772 case 'E': // down relative N rows, and to col 0 775 case 'E': // down relative N rows, and to col 0
773 arg = _csi_arg_get(&b); 776 arg = _csi_arg_get(&b);
@@ -775,8 +778,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
775 DBG("down relative %d rows, and to col 0", arg); 778 DBG("down relative %d rows, and to col 0", arg);
776 ty->termstate.wrapnext = 0; 779 ty->termstate.wrapnext = 0;
777 ty->cursor_state.cy += arg; 780 ty->cursor_state.cy += arg;
778 if (ty->cursor_state.cy < 0) ty->cursor_state.cy = 0; 781 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
779 else if (ty->cursor_state.cy >= ty->h) ty->cursor_state.cy = ty->h - 1;
780 ty->cursor_state.cx = 0; 782 ty->cursor_state.cx = 0;
781 break; 783 break;
782 case 'F': // up relative N rows, and to col 0 784 case 'F': // up relative N rows, and to col 0
@@ -785,8 +787,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
785 DBG("up relative %d rows, and to col 0", arg); 787 DBG("up relative %d rows, and to col 0", arg);
786 ty->termstate.wrapnext = 0; 788 ty->termstate.wrapnext = 0;
787 ty->cursor_state.cy -= arg; 789 ty->cursor_state.cy -= arg;
788 if (ty->cursor_state.cy < 0) ty->cursor_state.cy = 0; 790 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
789 else if (ty->cursor_state.cy >= ty->h) ty->cursor_state.cy = ty->h - 1;
790 ty->cursor_state.cx = 0; 791 ty->cursor_state.cx = 0;
791 break; 792 break;
792 case 'X': // erase N chars 793 case 'X': // erase N chars
@@ -1029,7 +1030,9 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
1029 if (!arg) 1030 if (!arg)
1030 { 1031 {
1031 ty->cursor_state.cx = cx; 1032 ty->cursor_state.cx = cx;
1033 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
1032 ty->cursor_state.cy = cy; 1034 ty->cursor_state.cy = cy;
1035 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
1033 } 1036 }
1034 } 1037 }
1035 break; 1038 break;
@@ -1569,17 +1572,20 @@ _handle_esc(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
1569 case 'M': // move to prev line 1572 case 'M': // move to prev line
1570 ty->termstate.wrapnext = 0; 1573 ty->termstate.wrapnext = 0;
1571 ty->cursor_state.cy--; 1574 ty->cursor_state.cy--;
1575 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
1572 termpty_text_scroll_rev_test(ty, EINA_TRUE); 1576 termpty_text_scroll_rev_test(ty, EINA_TRUE);
1573 return 1; 1577 return 1;
1574 case 'D': // move to next line 1578 case 'D': // move to next line
1575 ty->termstate.wrapnext = 0; 1579 ty->termstate.wrapnext = 0;
1576 ty->cursor_state.cy++; 1580 ty->cursor_state.cy++;
1581 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
1577 termpty_text_scroll_test(ty, EINA_FALSE); 1582 termpty_text_scroll_test(ty, EINA_FALSE);
1578 return 1; 1583 return 1;
1579 case 'E': // add \n\r 1584 case 'E': // add \n\r
1580 ty->termstate.wrapnext = 0; 1585 ty->termstate.wrapnext = 0;
1581 ty->cursor_state.cx = 0; 1586 ty->cursor_state.cx = 0;
1582 ty->cursor_state.cy++; 1587 ty->cursor_state.cy++;
1588 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
1583 termpty_text_scroll_test(ty, EINA_FALSE); 1589 termpty_text_scroll_test(ty, EINA_FALSE);
1584 return 1; 1590 return 1;
1585 case 'Z': // same a 'ESC [ Pn c' 1591 case 'Z': // same a 'ESC [ Pn c'
diff --git a/src/bin/termptyops.c b/src/bin/termptyops.c
index e9d93f8..d35900c 100644
--- a/src/bin/termptyops.c
+++ b/src/bin/termptyops.c
@@ -7,6 +7,7 @@
7#include "termptygfx.h" 7#include "termptygfx.h"
8#include "termptysave.h" 8#include "termptysave.h"
9#include "miniview.h" 9#include "miniview.h"
10#include <assert.h>
10 11
11#undef CRITICAL 12#undef CRITICAL
12#undef ERR 13#undef ERR
@@ -151,6 +152,7 @@ termpty_text_scroll_test(Termpty *ty, Eina_Bool clear)
151 { 152 {
152 termpty_text_scroll(ty, clear); 153 termpty_text_scroll(ty, clear);
153 ty->cursor_state.cy = e - 1; 154 ty->cursor_state.cy = e - 1;
155 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
154 } 156 }
155} 157}
156 158
@@ -164,6 +166,7 @@ termpty_text_scroll_rev_test(Termpty *ty, Eina_Bool clear)
164 { 166 {
165 termpty_text_scroll_rev(ty, clear); 167 termpty_text_scroll_rev(ty, clear);
166 ty->cursor_state.cy = b; 168 ty->cursor_state.cy = b;
169 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
167 } 170 }
168} 171}
169 172
@@ -186,6 +189,7 @@ termpty_text_append(Termpty *ty, const Eina_Unicode *codepoints, int len)
186 ty->termstate.wrapnext = 0; 189 ty->termstate.wrapnext = 0;
187 ty->cursor_state.cx = 0; 190 ty->cursor_state.cx = 0;
188 ty->cursor_state.cy++; 191 ty->cursor_state.cy++;
192 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cy, 0, ty->h);
189 termpty_text_scroll_test(ty, EINA_TRUE); 193 termpty_text_scroll_test(ty, EINA_TRUE);
190 cells = &(TERMPTY_SCREEN(ty, 0, ty->cursor_state.cy)); 194 cells = &(TERMPTY_SCREEN(ty, 0, ty->cursor_state.cy));
191 } 195 }
@@ -220,7 +224,10 @@ termpty_text_append(Termpty *ty, const Eina_Unicode *codepoints, int len)
220 if (EINA_UNLIKELY(ty->cursor_state.cx >= (ty->w - offset))) 224 if (EINA_UNLIKELY(ty->cursor_state.cx >= (ty->w - offset)))
221 ty->termstate.wrapnext = 1; 225 ty->termstate.wrapnext = 1;
222 else 226 else
223 ty->cursor_state.cx += offset; 227 {
228 ty->cursor_state.cx += offset;
229 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
230 }
224 } 231 }
225 else 232 else
226 { 233 {
@@ -235,8 +242,10 @@ termpty_text_append(Termpty *ty, const Eina_Unicode *codepoints, int len)
235 if (ty->cursor_state.cx > (ty->w - offset)) 242 if (ty->cursor_state.cx > (ty->w - offset))
236 { 243 {
237 ty->cursor_state.cx = ty->w - offset; 244 ty->cursor_state.cx = ty->w - offset;
245 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
238 return; 246 return;
239 } 247 }
248 TERMPTY_RESTRICT_FIELD(ty->cursor_state.cx, 0, ty->w);
240 } 249 }
241 } 250 }
242} 251}
@@ -248,6 +257,8 @@ termpty_clear_line(Termpty *ty, Termpty_Clear mode, int limit)
248 int n = 0; 257 int n = 0;
249 Evas_Coord x = 0, y = ty->cursor_state.cy; 258 Evas_Coord x = 0, y = ty->cursor_state.cy;
250 259
260 assert (y >= 0 && y < ty->h);
261
251 switch (mode) 262 switch (mode)
252 { 263 {
253 case TERMPTY_CLR_END: 264 case TERMPTY_CLR_END: