]> git.neil.brown.name Git - edlib.git/commitdiff
render-lines: avoid looping indefinitely when shifting.
authorNeilBrown <neil@brown.name>
Sun, 3 Sep 2023 09:16:51 +0000 (19:16 +1000)
committerNeilBrown <neil@brown.name>
Mon, 4 Sep 2023 23:07:53 +0000 (09:07 +1000)
If <rtab> is used for markup when wrap is enabled, and if the cursor is
at the end of the list, it is impossible to shift enough that there is
room for the cursor after the text.
So the shift loop continues endlessly.

Put a hard limit on this, and use a consistent limit in the other places
that we shift.

Signed-off-by: NeilBrown <neil@brown.name>
render-lines.c

index b8580625189e267766344add5c0f1ee7cfe05ef9..3b6567d289d3d739b109c192e8a0dc77eaf1f7bc 100644 (file)
@@ -658,12 +658,15 @@ static void find_lines(struct mark *pm safe, struct pane *p safe,
        if (start->mdata) {
                struct pane *hp = start->mdata;
                int curs_width;
+               int shifts = 0;
                found_end = measure_line(p, focus, start, offset) & 2;
 
                curs_width = pane_attr_get_int(
                        start->mdata, "curs_width", 1);
                if (curs_width <= 0)
                        curs_width = 1;
+               // FIXME this loops indefinitely if cursor after
+               // right-justified text.
                while (!rl->do_wrap && !rl->shift_locked &&
                       hp->cx + curs_width >= p->w) {
                        int shift = 8 * curs_width;
@@ -671,6 +674,8 @@ static void find_lines(struct mark *pm safe, struct pane *p safe,
                                shift = hp->cx;
                        rl->shift_left += shift;
                        measure_line(p, focus, start, offset);
+                       if (shifts++ > 100)
+                               break;
                }
                /* ->cy is top of cursor, we want to measure from bottom */
                line_height_pre = attr_find_int(start->mdata->attrs, "line-height");
@@ -1040,7 +1045,7 @@ static int revalidate_start(struct rl_data *rl safe,
        /* This loop is fragile and sometimes spins.  So ensure we
         * never loop more than 1000 times.
         */
-       if (pm && !rl->do_wrap && !rl->shift_locked && shifts++ < 1000) {
+       if (pm && !rl->do_wrap && !rl->shift_locked && shifts++ < 100) {
                int prefix_len;
                int curs_width;
                /* Need to check if side-shift is needed on cursor line */
@@ -1068,7 +1073,7 @@ static int revalidate_start(struct rl_data *rl safe,
                        curs_width = pane_attr_get_int(
                                m->mdata, "curs_width", 1);
 
-                       while (hp->cx + curs_width > p->w && shifts++ < 1000) {
+                       while (hp->cx + curs_width > p->w && shifts++ < 100) {
                                int shift = 8 * curs_width;
                                if (shift > hp->cx)
                                        shift = hp->cx;
@@ -1083,7 +1088,7 @@ static int revalidate_start(struct rl_data *rl safe,
                        while ((hp->cx < prefix_len
                                || (cols-rl->shift_left) + curs_width * 8 + curs_width < p->w) &&
                               rl->shift_left > 0 &&
-                              shifts++ < 1000 &&
+                              shifts++ < 100 &&
                               hp->cx + curs_width * 8 < p->w) {
                                int shift = 8 * curs_width;
                                if (shift > rl->shift_left)