]> git.neil.brown.name Git - edlib.git/commitdiff
Allow a line boundary to be reported by the document.
authorNeilBrown <neil@brown.name>
Tue, 31 Jan 2023 01:07:12 +0000 (12:07 +1100)
committerNeilBrown <neil@brown.name>
Mon, 6 Feb 2023 05:48:18 +0000 (16:48 +1100)
Rendering renders up to a line boundary.  Usually a newline, but the doc
can say where it is.  This allows multi-part to put a boundary between
parts, in case a part contains garbage.

This removes some blank lines in email messages -  nice.

Signed-off-by: NeilBrown <neil@brown.name>
doc-email.c
doc-multipart.c
lib-markup.c

index 7a573da4c0e57888747c36eca0a8f1aed53820e9..a4d3c3307a0a2e326f6458be3113da3cd77fd7df 100644 (file)
@@ -825,7 +825,7 @@ DEF_CMD(open_email)
 
        /* create spacer doc to be attached between each part */
        p = call_ret(pane, "doc:from-text", p, 0, NULL, NULL, 0, NULL,
-                    "\n0123456789\n");
+                    "0123456789\n");
        if (!p)
                goto out;
 
@@ -834,7 +834,6 @@ DEF_CMD(open_email)
        spacer = p;
        point = vmark_new(p, MARK_POINT, NULL);
        call("doc:set-ref", p, 1, point);
-       doc_next(p, point);
        call("doc:set-attr", p, 1, point, "markup:func", 0,
             NULL, "doc:email:render-spacer");
        mark_free(point);
index 735a8f1e7b4bfa37d5b7abbaba3dbe3ceaa9d43a..c911398a72b07f3cb625961bf34a2554c2bb1f99 100644 (file)
@@ -435,6 +435,19 @@ DEF_CMD(mp_step_part)
        return m->ref.docnum + 1;
 }
 
+DEF_CMD(mp_get_boundary)
+{
+       /* return a mark past which rendering must not go. */
+       struct mark *m = ci->mark;
+
+       if (!m || !ci->comm2)
+               return Enoarg;
+       m = mark_dup(m);
+       call("doc:step-part", ci->home, ci->num, m);
+       comm_call(ci->comm2, "cb", ci->focus, 0, m);
+       return 1;
+}
+
 struct mp_cb {
        struct command c;
        struct command *cb;
@@ -793,6 +806,7 @@ static void mp_init_map(void)
        key_add(mp_map, "doc:get-attr", &mp_attr);
        key_add(mp_map, "doc:set-attr", &mp_set_attr);
        key_add(mp_map, "doc:step-part", &mp_step_part);
+       key_add(mp_map, "doc:get-boundary", &mp_get_boundary);
        key_add(mp_map, "Close", &mp_close);
        key_add(mp_map, "Free", &mp_free);
        key_add(mp_map, "Notify:Close", &mp_notify_close);
index ddf4eccbd983c4cbcb6e18fbcd677e389ab8540b..3a1037addc6a69d6506093ecd9088fc5aeaaec74 100644 (file)
@@ -45,6 +45,7 @@ DEF_CMD(render_prev)
        struct pane *f = ci->focus;
        struct mu_info *mu = ci->home->data;
        struct mark *boundary = NULL;
+       struct mark *doc_boundary = NULL;
        int count = 0;
        int rpt = RPT_NUM(ci);
        wint_t ch;
@@ -52,22 +53,29 @@ DEF_CMD(render_prev)
        if (!m)
                return Enoarg;
 
-       if (!rpt)
+       if (!rpt) {
                boundary = vmark_at_or_before(f, m, mu->view, ci->home);
+               doc_boundary = call_ret(mark, "doc:get-boundary", f, -1, m);
+       }
        while ((ch = doc_prev(f, m)) != WEOF &&
               (!is_eol(ch) || rpt > 0) &&
               count < LARGE_LINE &&
-              (!boundary || mark_ordered_not_same(boundary, m))) {
-               if (rpt)
+              (!boundary || mark_ordered_not_same(boundary, m)) &&
+              (!doc_boundary || mark_ordered_not_same(doc_boundary, m))) {
+               if (rpt) {
                        boundary = vmark_at_or_before(f, m, mu->view, ci->home);
+                       doc_boundary = call_ret(mark, "doc:get-boundary", f, -1, m);
+               }
                rpt = 0;
                count += 1;
        }
-       if (ch != WEOF && !is_eol(ch)) {
+       if (ch != WEOF && !is_eol(ch) &&
+           (!doc_boundary || !mark_same(doc_boundary, m))) {
                /* Just cross the boundary, or the max count.
                 * Need to step back, and ensure there is a stable boundary
                 * here.
                 */
+               mark_free(doc_boundary);
                doc_next(f, m);
                if (!boundary || !mark_same(boundary, m)) {
                        boundary = vmark_new(f, mu->view, ci->home);
@@ -76,6 +84,7 @@ DEF_CMD(render_prev)
                }
                return 1;
        }
+       mark_free(doc_boundary);
        if (ch == WEOF && rpt)
                return Efail;
        /* Found a '\n', so step forward over it for start-of-line. */
@@ -273,6 +282,7 @@ DEF_CMD(render_line)
        struct mark *m = ci->mark;
        struct mark *pm = ci->mark2; /* The location to render as cursor */
        struct mark *boundary, *start_boundary = NULL;
+       struct mark *doc_boundary;
        int o = ci->num;
        wint_t ch;
        int chars = 0;
@@ -318,6 +328,8 @@ DEF_CMD(render_line)
                        start_boundary = boundary;
                boundary = vmark_next(boundary);
        }
+       doc_boundary = call_ret(mark, "doc:get-boundary", focus, 1, m);
+
        buf_init(&b);
        call_comm("map-attr", focus, &ar.rtn, 0, m, "start-of-line");
        while (1) {
@@ -360,6 +372,8 @@ DEF_CMD(render_line)
                }
                if (boundary && mark_ordered_or_same(boundary, m))
                        break;
+               if (doc_boundary && mark_ordered_or_same(doc_boundary, m))
+                       break;
                if (ch == '<') {
                        if (o >= 0 && b.len+1 >= o) {
                                doc_prev(focus, m);
@@ -402,6 +416,8 @@ DEF_CMD(render_line)
                /* This boundary is no longer well-placed. */
                mark_free(start_boundary);
 
+       mark_free(doc_boundary);
+
        ret = comm_call(ci->comm2, "callback:render", focus, 0, NULL,
                        buf_final(&b));
        free(b.b);