]> git.neil.brown.name Git - edlib.git/commitdiff
Change rules for doc:render-line with mark2
authorNeilBrown <neil@brown.name>
Sun, 28 May 2023 02:34:01 +0000 (12:34 +1000)
committerNeilBrown <neil@brown.name>
Thu, 8 Jun 2023 10:37:22 +0000 (20:37 +1000)
When doc:render-line is called with mark2, this doesn't interrupt the
rendering, but simply reports (via ->num in the callback) the offset
where mark2 was found.

Now ->num is either negative, or the number of chars to process.
NO_NUMERIC is no longer relevant and is not tested for.

I think this is simpler as ->num and ->mark2 are not independent.

Signed-off-by: NeilBrown <neil@brown.name>
12 files changed:
DOC/Developer/06-rendering.md
DOC/render-control
doc-docs.c
doc-email.c
lib-linefilter.c
lib-markup.c
python/lib-compose-email.py
python/module-notmuch.py
render-complete.c
render-format.c
render-hex.c
render-lines.c

index 9e1db36005e5528e1628e5964ca083425a91c261..9ee9424e2d2f6f0cc62c0cf9f38e1c359ae640a6 100644 (file)
@@ -155,9 +155,10 @@ markup to provide font size and colour etc.
 
 "render-lines" also understands that there is a need to map between
 location in the document and locations on the display.
-"doc:render-line" can be asked to only convert up to some location into
-a string, rather than the whole line.  This can be used to determine
-where in the markup the cursor should appear.
+"doc:render-line" can be asked to track when conversion reaches some
+mark, and to report the offset in the rendered string corresponding to
+this point.  This can be used to determine where in the markup the
+cursor should appear.
 
 As "render-lines" collects these marked-up strings, it creates sub-panes
 using "renderline" as described below to draw the marked-up string onto
@@ -424,21 +425,19 @@ length count is usually given as an extremely large number meaning
  - "doc:render-line"
      + mark - start of the line to be rendered.  Line continues until
        first '\n' or until 'num2' chars have been examined and no '\n'
-       found.  'mark' will be mvoe to the end of the range that was
+       found.  'mark' will be moved to the end of the range that was
        rendered (often to the end of line line / start of next line).
-     + mark2 - if num == -1, location not to render beyond.  This is
-       typically set to the current "point", and the cursor will be
-       drawn where the returned string ends.
+     + mark2 - location of interested to be reported as offset in the
+       rendering.  This is typically set to the current "point", and the
+       cursor will be drawn where the returned string ends.
      + num - if >= 0, maximum number of result character to return
        before aborting.  'mark' will be moved to the location that would
        draw at or beyond this place on the screen.  This can be used to
        convert a screen location (from a mouse click) back to a document
        location.
-       If num == -1, rendering stops when mark reaches mark2.  This
-       allows the cursor to be found, and action to be taken if it is
-       off-screen.
-       If num == NO_NUMERIC rendering continues to end-of-line.
-     + comm2 - a callback used to return the rendered string in "str1".
+       If num < 0 rendering continues to end-of-line.
+     + comm2 - a callback used to return the rendered string in "str1",
+       and the offset of mark2 (if given) in "num".
        The string will be freed after the callback returns, so it must
        be duplicated if later access is needed.
 
index 86c014815a3bea9492a1e15c39d6ad1b43122a4b..deb95a54053c509013ff635b39e45683e1b24987 100644 (file)
@@ -39,7 +39,7 @@ the given location.
         or until 'num2' chars have been examined with no '\n' found
         mark will be moved to the end of the range that was rendered (often
         the end of the line)
-  mark2: if num==-1, location not to render beyond.  This is typically set
+  mark2: location or record and report offset of.  This is typically set
        to the current "point", and a cursor will be drawn where the returned
        string end.
   num: if >= 0, max number of result characters to return before
@@ -47,9 +47,7 @@ the given location.
        at or beyond this place on the screen.  This can be used to
        convert a screen location (from a mouse click) back to a document
        location.
-       if == -1, Rendering stops when mark reaches mark2.  This allows the
-       cursor to be found, and action to be taken if it is off-screen
-       if == NO_NUMERIC, ignored.
+       if < 0, ignored.
   comm2: a callback used to return the rendered string in "str".  The string
        will be freed after the callback returns, so it must duplicate it if
        later access is needed.
index 38620f9440c7ae24561d76e99d90b913cea8fccc..4ad65d5cc4cff1007da8ac86cfa85f4519ee2e07 100644 (file)
@@ -207,6 +207,9 @@ DEF_CMD(docs_mod_next)
                return Enoarg;
        m = mark_dup(ci->mark);
        call("doc:EOL", ci->home->parent, 1, m, NULL, 1);
+       /* Passing '0' is deliberate.  We don't want to render
+        * anything, just see if there is anything tha could be rendered.
+        */
        if (call("doc:render-line", ci->focus, 0, m) < 0 ||
            m->ref.p == NULL) {
                mark_free(m);
index 49d2cca3ad4bd3b46825fbc0e0e51b4c095aa0ea..5b7b7c7cab80545b2d05aedec1f4c9a57c9e82eb 100644 (file)
@@ -76,22 +76,19 @@ static bool handle_rfc822(struct pane *email safe,
                          char *path safe);
 
 static bool cond_append(struct buf *b safe, char *txt safe, char *tag safe,
-                       int offset, int *cp safe)
+                       int offset, int *pos safe)
 {
        char *tagf = "active-tag:email-";
        int prelen = 1 + strlen(tagf) + strlen(tag) + 1 + 1;
        int postlen = 1 + 3;
        int len = prelen + strlen(txt) + postlen;
-       if (offset != NO_NUMERIC && offset >= 0 && offset <= b->len + len)
+       if (offset >= 0 && offset <= b->len + len)
                return False;
        buf_concat(b, "<");
        buf_concat(b, tagf);
        buf_concat(b, tag);
        buf_concat(b, ">[");
-       if (*cp == 0)
-               return False;
-       if (*cp > 0)
-               *cp -= 1;
+       *pos = b->len;
        buf_concat(b, txt);
        buf_concat(b, "]</>");
        return True;
@@ -117,6 +114,7 @@ DEF_CMD(email_spacer)
        struct mark *pm = ci->mark2;
        int o = ci->num;
        int cp = -1;
+       int ret_pos = 0;
        char *attr;
        int ret;
        bool ok = True;
@@ -158,22 +156,27 @@ DEF_CMD(email_spacer)
                attr = "hide";
 
        while (ok && attr && *attr) {
+               int pos = 0;
                char *a = strchr(attr, ':');
                if (a)
                        *a = 0;
                if (is_attr("hide", attr))
                        ok = cond_append(&b, visible ? "HIDE" : "SHOW", attr,
-                                        o, &cp);
+                                        o, &pos);
                else if (is_attr("full", attr))
                        ok = cond_append(&b, orig ? "BRIEF" : "FULL", attr,
-                                        o, &cp);
+                                        o, &pos);
                else if (is_attr("extras", attr))
                        ok = cond_append(&b, extras ? "-" : "EXTRAS", attr,
-                                        o, &cp);
+                                        o, &pos);
                else
-                       ok = cond_append(&b, attr, attr, o, &cp);
+                       ok = cond_append(&b, attr, attr, o, &pos);
                if (ok)
                        doc_next(ci->focus, m);
+               if (cp >= 0) {
+                       cp -= 1;
+                       ret_pos = pos;
+               }
                attr = a;
                if (attr)
                        *attr++ = ':';
@@ -185,7 +188,7 @@ DEF_CMD(email_spacer)
         * if cp > 0, we haven't reached cursor yet, so don't stop
         * if cp == 0, this is cursor pos, so stop.
         */
-       if (ok && cp != 0 && ((o < 0 || o == NO_NUMERIC))) {
+       if (ok && o < 0) {
                wint_t wch;
                buf_concat(&b, "</>");
                attr = pane_mark_attr(ci->focus, m,
@@ -206,13 +209,17 @@ DEF_CMD(email_spacer)
                        buf_concat(&b, " file=");
                        buf_concat(&b, attr);
                }
+               if (cp >= 0)
+                       ret_pos = b.len;
                buf_concat(&b, "\n");
+               if (cp >= 1)
+                       ret_pos = b.len;
                while ((wch = doc_next(ci->focus, m)) &&
                       wch != '\n' && wch != WEOF)
                        ;
        }
 
-       ret = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL,
+       ret = comm_call(ci->comm2, "callback:render", ci->focus, ret_pos, NULL,
                        buf_final(&b));
        free(b.b);
        return ret;
@@ -232,6 +239,7 @@ DEF_CMD(email_image)
        char *c = NULL;
        int p;
        int ret;
+       int retlen = 0;
        int i;
        struct xy scale;
        struct mark *point = ci->mark2;
@@ -255,17 +263,15 @@ DEF_CMD(email_image)
                c[max_chars] = '\0';
 
        for (i = 0; i < 9 ; i++) {
-               if (point && mark_ordered_or_same(point, ci->mark)) {
-                       c[map_start + i] = 0;
-                       break;
-               }
+               if (point && mark_ordered_or_same(point, ci->mark))
+                       retlen = map_start + i;
                if (max_chars >= 0 && map_start + i >= max_chars)
                        break;
                doc_next(ci->focus, ci->mark);
        }
 
        ret = comm_call(ci->comm2, "callback:render", ci->focus,
-                       0, NULL, c);
+                       retlen, NULL, c);
        free(c);
        return ret;
 }
index a0b6fdb98005e554a6fb47735f00fb2db1d6666c..594e181b0d010a7dac79c1fff6667eedc1d2a358 100644 (file)
@@ -40,6 +40,7 @@ struct rlcb {
        struct filter_data *fd;
        int keep, cmp;
        const char *str;
+       int cursor_offset;
 };
 
 DEF_CB(rlcb)
@@ -73,6 +74,7 @@ DEF_CB(rlcb)
                        /* Want the original with markup */
                        strcpy(c, ci->str);
                cb->str = c;
+               cb->cursor_offset = ci->num;
        } else
                free(c);
        return 1;
@@ -169,9 +171,10 @@ DEF_CMD(render_filter_line)
                           ci->num, ci->mark, NULL, 0, m2) < 0)
                return Efail;
 
-       ret = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL, cb.str);
+       ret = comm_call(ci->comm2, "callback:render", ci->focus,
+                       cb.cursor_offset, NULL, cb.str);
        free((void*)cb.str);
-       if (ci->num != NO_NUMERIC)
+       if (m2)
                /* Was rendering to find a cursor, don't need to skip */
                return ret;
        /* Need to continue over other non-matching lines */
@@ -367,7 +370,7 @@ DEF_CMD(filter_changed)
                mark_to_mark(end, m);
        }
 
-       if (call("doc:render-line", ci->focus, NO_NUMERIC, end) > 0)
+       if (call("doc:render-line", ci->focus, -1, end) > 0)
                found_one = True;
 
        m = mark_dup(end);
@@ -451,7 +454,7 @@ DEF_CMD(filter_eol)
                struct call_return cr;
                cr.c = eol_cb;
                if (home_call(ci->home, "doc:render-line",
-                             ci->focus, NO_NUMERIC, ci->mark, NULL,
+                             ci->focus, -1, ci->mark, NULL,
                              0, NULL, NULL, 0,0, &cr.c) <= 0)
                        line = 1;
                line -= 1;
index 59f29a64dfd3fb0ff0139b0067555e7e61e13750..0369b2d56523a10fbb7b688b38b3e622e3c78774 100644 (file)
@@ -308,6 +308,7 @@ DEF_CMD(render_line)
        struct mark *boundary, *start_boundary = NULL;
        struct mark *doc_boundary;
        int o = ci->num;
+       int pm_offset = -1;
        wint_t ch;
        int chars = 0;
        int ret;
@@ -317,9 +318,6 @@ DEF_CMD(render_line)
        char *noret;
        char *attr;
 
-       if (o == NO_NUMERIC)
-               o = -1;
-
        ar.rtn = text_attr_callback;
        ar.fwd = text_attr_forward;
        ar.ast = ar.tmpst = NULL;
@@ -367,8 +365,8 @@ DEF_CMD(render_line)
 
                if (o >= 0 && b.len >= o)
                        break;
-               if (pm && mark_same(m, pm))
-                       break;
+               if (pm && mark_same(m, pm) && pm_offset < 0)
+                       pm_offset = b.len;
 
                if (ar.ast && ar.min_end <= chars) {
                        int depth = find_finished(ar.ast, chars, &ar.min_end);
@@ -461,7 +459,10 @@ DEF_CMD(render_line)
 
        mark_free(doc_boundary);
 
-       ret = comm_call(ci->comm2, "callback:render", focus, 0, NULL,
+       if (pm && pm_offset < 0)
+               pm_offset = b.len;
+
+       ret = comm_call(ci->comm2, "callback:render", focus, pm_offset, NULL,
                        buf_final(&b));
        free(b.b);
        free(ar.insert.b);
index e04cdc90a8c86f5db10eed3d3dfd6984e4124e87..654a17a3b69eccf4d04f3adf09107c8ddff31fe7 100644 (file)
@@ -331,10 +331,6 @@ class compose_email(edlib.Pane):
 
     def markup_header(self, key, focus, num, mark, mark2, comm2, **a):
         "handle:compose:markup-header"
-        # Display cursor at start or end, anything else should be suppressed.
-        if num == 0 or (mark2 and mark2 == mark):
-            # appear at the start of the line
-            return comm2("cb", focus, "<fg:red>")
         # at least go to end of line
         self.parent.call("doc:EOL", 1, mark)
         m = self.vmark_at_or_before(self.view, mark)
@@ -348,11 +344,13 @@ class compose_email(edlib.Pane):
             info = m['compose-info']
             if info:
                 markup += ' - ' + info
-        if (num == edlib.NO_NUMERIC or num < 0) and (not mark2 or mark2 > mark):
+        if num < 0:
             # normal render - go past eol
             self.parent.next(mark)
             markup += "</>\n"
-        return comm2("cb", focus, markup)
+        # return num==0 to display cursor at start or end, anything else
+        # should be suppressed.
+        return comm2("cb", focus, 0, markup)
 
     def handle_clone(self, key, focus, **a):
         "handle:Clone"
index 6dacf8313774fd6989d83c97024ed193d4d37ac9..5d4c45841c5e4261b3d2a46dbc8afd0675fd72f5 100644 (file)
@@ -3545,12 +3545,12 @@ class notmuch_message_view(edlib.Pane):
             return edlib.Efallthrough
         mark.to_mark(p.next())
         eol="\n"
-        if mark2 or num > 0 and num < 2000:
+        if num > 0 and num < 2000:
             # don't show eol
             self.prev(mark)
             eol = ""
         if comm2:
-            comm2("cb", focus, "<fg:yellow,bg:blue+30>%d quoted lines</>%s" % (int(p['quote-length']), eol))
+            comm2("cb", focus, 0, "<fg:yellow,bg:blue+30>%d quoted lines</>%s" % (int(p['quote-length']), eol))
         return 1
 
     def handle_render_line_prev(self, key, focus, num, mark, comm2, **a):
index a365d0f51cb68bbbb489bcfa367d5bdcedca9604..318071665985ba6e781a5178ae02cef49fb76580 100644 (file)
@@ -99,7 +99,7 @@ DEF_CMD(render_complete_line)
                return Enoarg;
 
        m = mark_dup(ci->mark);
-       line = call_ret(str, ci->key, ci->home->parent, NO_NUMERIC, m);
+       line = call_ret(str, ci->key, ci->home->parent, -1, m);
        if (!line) {
                mark_free(m);
                return Efail;
@@ -110,7 +110,7 @@ DEF_CMD(render_complete_line)
                startlen = 0;
        else
                startlen = start - line;
-       if (ci->num >= 0 && ci->num != NO_NUMERIC) {
+       if (ci->num >= 0) {
                /* Only want 'num' bytes from start, with ->mark positioned.
                 * So need to find how many bytes of 'line' produce num bytes
                 * of highlighted line.
@@ -123,7 +123,7 @@ DEF_CMD(render_complete_line)
                mark_free(m);
                line = call_ret(str, ci->key, ci->home->parent,
                                num, ci->mark);
-       } else if (ci->mark2) {
+       } else if (ci->mark2) { //FIXME
                /* Only want up-to the cursor, which might be in the middle of
                 * the highlighted region.  Now we know where that is, we can
                 * highlight whatever part is still visible.
@@ -477,7 +477,7 @@ DEF_CMD(complete_return)
        /* Go to start of line */
        home_call(ci->home, "doc:render-line-prev", ci->home, 0, ci->mark);
        home_call(ci->home, "doc:render-line",
-                 ci->home, NO_NUMERIC, ci->mark, NULL, 0, NULL,
+                 ci->home, -1, ci->mark, NULL, 0, NULL,
                  NULL, 0,0, &cr.c);
        if (!cr.s)
                return 1;
index 8e562f4ff8d23189a8153e8eb3bfa8ab90360665..ac61951f96dcb5881b068fea60e2505c8d27efed 100644 (file)
@@ -196,12 +196,12 @@ DEF_CMD(render_line)
 
        if (pm && !mark_same(pm, m))
                pm = NULL;
-       if (ci->num == NO_NUMERIC || ci->num < 0)
+       if (ci->num < 0)
                len = -1;
        else
                len = ci->num;
        ret = do_format(ci->focus, ci->mark, pm, len, 1);
-       if (!pm && len < 0)
+       if (len < 0)
                doc_next(ci->focus, m);
        rv = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL, ret);
        free(ret);
index ce5c2bc5078ce3e45bac8405698a080919066611..ca7b1e70a7eafa59a4e0a47078548a5bc1f773e6 100644 (file)
@@ -101,6 +101,7 @@ DEF_CMD(render_line)
        struct mark *m = NULL;
        struct mark *pm = ci->mark2;
        int pos;
+       int pm_offset = -1;
        int i;
        char buf[30];
        int rv;
@@ -121,10 +122,9 @@ DEF_CMD(render_line)
                wint_t ch;
                struct mark *m2 = ci->mark;
 
-               if (pm && mark_same(m2, pm))
-                       goto done;
-               if (ci->num >= 0 && ci->num != NO_NUMERIC &&
-                   ci->num <= ret.len)
+               if (pm && mark_same(m2, pm) && pm_offset < 0)
+                       pm_offset = ret.len;
+               if (ci->num >= 0 && ci->num <= ret.len)
                        goto done;
 
                ch = doc_next(ci->focus, m2);
@@ -158,7 +158,7 @@ DEF_CMD(render_line)
 done:
        if (m)
                mark_free(m);
-       rv = comm_call(ci->comm2, "callback:render", ci->focus, 0, NULL,
+       rv = comm_call(ci->comm2, "callback:render", ci->focus, pm_offset, NULL,
                       buf_final(&ret));
        free(ret.b);
        return rv ?: 1;
index 548ad4bbd0e1dac58ea2eff6d48b492be74c8900..b334a3bc6ea541f4d143ee2e61707d90642bda3c 100644 (file)
@@ -9,14 +9,14 @@
  * This takes a mark and moves it to the end of the rendered line
  * so that another call will produce another line.
  * "doc:render-line" must always return a full line including '\n'
- * unless the result would be bigger than the 'max' passed in ->num or,
- * when ->num==-1, unless the rendering would go beyond the location in
- * ->mark2.  In these cases it can stop before a '\n'.  In each case,
+ * unless the result would be bigger than the 'max' passed in ->num or
+ * ->num < 0.  In these cases it can stop before a '\n'.  In each case,
  * the mark is moved to the end of the region that was rendered;
- * This allows a mark to be found for a given character position, or a display
- * position found for a given mark.
+ * This allows a mark to be found for a given character position.
+ * If mark2 is given, the offset in the rendering when mark2 is reached
+ * is reported as ->num in the callback.
  * For the standard 'render the whole line' functionality, ->num should
- * be NO_NUMERIC
+ * be negative.
  *
  * The document or filter must also provide "doc:render-line-prev" which
  * moves mark to a start-of-line.  If num is 0, then don't skip over any
@@ -267,7 +267,7 @@ static void call_render_line(struct pane *home safe, struct pane *p safe,
                }
                s = "";
        } else
-               s = call_ret(strsave, "doc:render-line", p, NO_NUMERIC, m);
+               s = call_ret(strsave, "doc:render-line", p, -1, m);
 
        if (!mark_valid(start)) {
                mark_free(m);
@@ -324,16 +324,12 @@ static struct mark *call_render_line_offset(struct pane *p safe,
        return m;
 }
 
-DEF_CMD(get_len)
+DEF_CMD(get_offset)
 {
-       if (ci->str) {
-               int l = strlen(ci->str);
-               while (l >=4 && strncmp(ci->str+l-3, "</>", 3) == 0 &&
-               ci->str[l-4] != '<')
-                       l -= 3;
-               return l + 1;
-       } else
+       if (ci->num < 0)
                return 1;
+       else
+               return ci->num + 1;
 }
 
 static int call_render_line_to_point(struct pane *p safe, struct mark *pm safe,
@@ -342,7 +338,7 @@ static int call_render_line_to_point(struct pane *p safe, struct mark *pm safe,
        int len;
        struct mark *m = mark_dup_view(start);
 
-       len = call_comm("doc:render-line", p, &get_len, -1, m, NULL, 0, pm);
+       len = call_comm("doc:render-line", p, &get_offset, -1, m, NULL, 0, pm);
        mark_free(m);
        if (len <= 0)
                return 0;