]> git.neil.brown.name Git - edlib.git/commitdiff
render-line:measure now reports if the line ended properly
authorNeilBrown <neil@brown.name>
Fri, 18 Aug 2023 07:09:20 +0000 (17:09 +1000)
committerNeilBrown <neil@brown.name>
Fri, 18 Aug 2023 19:32:25 +0000 (05:32 +1000)
If the last line in a document doesn't end with a newline character, we
need to handle that interesting case.
Make it easier to do so.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
lib-renderline.c
render-lines.c

index df9b5a36880be9bec10eb72a5119c1f24193177d..128dbf714e79071f3b3b98ca1b031a9111623f60 100644 (file)
@@ -27,7 +27,7 @@ the file.
 - [ ] When is left_margin used?  Can I use it for hanging indent?  If
       not, how do I do that?  Can I tab out, set margin, tab back for
       text?  Am I using points properly?
-- [ ] find a better way to handle "case when EOF is at the end" of
+- [X] find a better way to handle "case when EOF is at the end" of
       a non-empty line.
 - [ ] as renderline changes result if cursor is present, cursor pos
       must ALWAYS be given.
index c8f639246eff2c61932024305c8a12773679c2f0..7dad2bdb24e996014ebf6fc77548ae25b8a91ce9 100644 (file)
@@ -584,7 +584,7 @@ static int calc_tab(int num, int margin, int scale)
        return margin + num * scale / 1000;
 }
 
-static bool measure_line(struct pane *p safe, struct pane *focus safe, int offset)
+static int measure_line(struct pane *p safe, struct pane *focus safe, int offset)
 {
        /* First measure each render_item entry setting
         * height, ascent, width.
@@ -592,6 +592,11 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
         * each unit.
         * Finally identify line-break locations if needed and set 'y'
         * positions
+        *
+        * Return 1 if there is an EOL ('\n')
+        * 2 if there is an end-of-page ('\f')
+        * 3 if both.
+        * 0 if neither
         */
        struct rline_data *rd = &p->data;
        struct render_item *ri, *wraprl;
@@ -604,20 +609,23 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
        int xdiff, ydiff;
        struct call_return cr;
        int x, y;
-       bool eop = False;
+       int ret = 0;
        bool seen_rtab = False;
 
        if (!rd->content)
-               return eop;
+               return ret;
        if (xyscale.x == rd->scale && p->w == rd->measure_width &&
            shift_left == rd->measure_shift_left &&
            offset == rd->measure_offset) {
                /* No change */
-               for (ri = rd->content ; ri ; ri = ri->next)
+               for (ri = rd->content ; ri ; ri = ri->next) {
+                       if (ri->eol && rd->line[ri->start] == '\n')
+                               ret |= 1;
                        if (ri->eol && rd->line[ri->start] == '\f')
-                               eop = True;
+                               ret |= 2;
+               }
                pane_resize(p, p->x, p->y, p->w, rd->measure_height);
-               return eop;
+               return ret;
        }
        rd->scale = xyscale.x;
        rd->measure_width = p->w;
@@ -650,8 +658,10 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
                                /* Ensure attributes of newline add to line
                                 * height. The width will be ignored. */
                                strcpy(tmp, "M");
+                               if (rd->line[ri->start] == '\n')
+                                       ret |= 1;
                                if (rd->line[ri->start] == '\f')
-                                       eop = True;
+                                       ret |= 2;
                        } else if (rd->line[ri->start] == '\t') {
                                strcpy(tmp, " ");
                        } else {
@@ -863,7 +873,7 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
                ydiff + rd->line_height;
        pane_resize(p, p->x, p->y, p->w, rd->measure_height);
        attr_set_int(&p->attrs, "line-height", rd->line_height);
-       return eop;
+       return ret;
 }
 
 static void draw_line(struct pane *p safe, struct pane *focus safe, int offset)
@@ -1221,13 +1231,14 @@ DEF_CMD(renderline_refresh)
 DEF_CMD(renderline_measure)
 {
        struct rline_data *rd = &ci->home->data;
-       bool end_of_page;
+       int ret;
+
        if (rd->image)
                return render_image(ci->home, ci->focus, rd->line,
                                    False, ci->num, False, 0, 0);
 
-       end_of_page = measure_line(ci->home, ci->focus,
-                                  ci->num < 0 ? -1 : rd->prefix_bytes + ci->num);
+       ret = measure_line(ci->home, ci->focus,
+                          ci->num < 0 ? -1 : rd->prefix_bytes + ci->num);
        rd->prefix_pixels = 0;
        if (rd->prefix_bytes) {
                struct xy xy = find_curs(ci->home, rd->prefix_bytes, NULL);
@@ -1238,12 +1249,12 @@ DEF_CMD(renderline_measure)
                const char *cursattr = NULL;
                struct xy xy;
                xy = find_curs(ci->home, rd->prefix_bytes + ci->num, &cursattr);
-               comm_call(ci->comm2, "cb", ci->focus, end_of_page, NULL,
+               comm_call(ci->comm2, "cb", ci->focus, ret, NULL,
                          cursattr);
                ci->home->cx = xy.x;
                ci->home->cy = xy.y;
        }
-       return end_of_page ? 2 : 1;
+       return ret | 4;
 }
 
 DEF_CMD(renderline_findxy)
index bf1361953f520cbeae69c8e3aac14053f4c47c81..3d48599199b3a522807c4eaf6673382cfa53be8c 100644 (file)
@@ -166,7 +166,7 @@ static bool vmark_is_valid(struct mark *m safe)
 }
 
 /* Returns 'true' at end-of-page */
-static bool _measure_line(struct pane *p safe, struct pane *focus safe,
+static int _measure_line(struct pane *p safe, struct pane *focus safe,
                          struct mark *mk safe, short cursor_offset,
                          char **cursor_attr)
 {
@@ -181,20 +181,20 @@ static bool _measure_line(struct pane *p safe, struct pane *focus safe,
        if (cursor_attr)
                *cursor_attr = cr.s;
        /* end-of-page flag */
-       return cr.ret == 2;
+       return cr.ret & 3;
 }
 #define measure_line(...) VFUNC(measure_line, __VA_ARGS__)
-static inline bool measure_line3(struct pane *p safe, struct pane *focus safe,
+static inline int measure_line3(struct pane *p safe, struct pane *focus safe,
                                 struct mark *mk safe)
 {
        return _measure_line(p, focus, mk, -1, NULL);
 }
-static inline bool measure_line4(struct pane *p safe, struct pane *focus safe,
+static inline int measure_line4(struct pane *p safe, struct pane *focus safe,
                                 struct mark *mk safe, short cursor_offset)
 {
        return _measure_line(p, focus, mk, cursor_offset, NULL);
 }
-static inline bool measure_line5(struct pane *p safe, struct pane *focus safe,
+static inline int measure_line5(struct pane *p safe, struct pane *focus safe,
                                 struct mark *mk safe, short cursor_offset,
                                 char **cursor_attr)
 {
@@ -648,7 +648,7 @@ static void find_lines(struct mark *pm safe, struct pane *p safe,
        if (start->mdata) {
                struct pane *hp = start->mdata;
                int curs_width;
-               found_end = measure_line(p, focus, start, offset);
+               found_end = measure_line(p, focus, start, offset) & 2;
 
                curs_width = pane_attr_get_int(
                        start->mdata, "curs_width", 1);
@@ -1115,10 +1115,12 @@ static int revalidate_start(struct rl_data *rl safe,
        start_of_file = doc_prior(focus, start) == WEOF;
        for (m = start; m && !found_end && y < p->h; m = vmark_next(m)) {
                struct pane *hp;
+               int found;
                if (refresh_all)
                        vmark_invalidate(m);
                call_render_line(p, focus, m, NULL);
-               found_end = measure_line(p, focus, m);
+               found = measure_line(p, focus, m);
+               found_end = found & 2;
                hp = m->mdata;
                if (!mark_valid(m) || !hp)
                        break;
@@ -1132,12 +1134,12 @@ static int revalidate_start(struct rl_data *rl safe,
                }
                y += hp->h;
                m2 = vmark_next(m);
-               /* The doc_prior handles case when EOF is at the end
+               /* The "found & 1" handles case when EOF is at the end
                 * of a non-empty line.
                 */
                if (pm && m2 && mark_ordered_or_same(m, pm) &&
                    (mark_ordered_not_same(pm, m2) ||
-                    (mark_same(pm, m2) && !is_eol(doc_prior(focus,m2))))) {
+                    (mark_same(pm, m2) && !(found & 1)))) {
 
                        /* Cursor is on this line */
                        int offset = call_render_line_to_point(focus,