]> git.neil.brown.name Git - edlib.git/commitdiff
Change rules for mark passed to doc:content
authorNeilBrown <neil@brown.name>
Sun, 4 Jun 2023 02:34:59 +0000 (12:34 +1000)
committerNeilBrown <neil@brown.name>
Wed, 28 Jun 2023 05:40:21 +0000 (15:40 +1000)
The 'start' mark passed to doc:content must not now be changed.
Some handlers did change it, others didn't.
Several callers didn't want it changed (so passed dup), a few didn't
care.

Due to the extra chars that can be passed, it might be awkward to return
a precise mark, and the caller might not care.
So leave it up to the callback to report any marks needed, and always
dup the mark before moving it.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
core-doc.c
doc-multipart.c
emacs-search.c
lib-crop.c
lib-linecount.c
lib-search.c
python/lib-diff.py
python/render-calc.py
render-format.c

index 681b7beed4cee60cc44c2a48c2d289a906618b1a..5713744d3fe2669be9ef3d7e1144b1af558d1dd1 100644 (file)
@@ -10,7 +10,7 @@ the file.
 ### Trivial
 
 - [ ] If an email part doesn't end with newline, last character is swallowed.
-- [ ] What is rule for doc:content?  Does the mark move and get passed
+- [X] What is rule for doc:content?  Does the mark move and get passed
       down, or is it copied and left unchanged?
 
 ### Small
index b936f1ce6a8a4f7fb9a4e4b54d54314bb9e50514..071c4e6a3cf8b473d9749fb2b73f4170ae595858 100644 (file)
@@ -822,9 +822,30 @@ DEF_CMD(doc_default_content)
         *
         * If called as doc:content-bytes: return bytes, not chars
         *
-        * .mark is 'location': to start.  This is moved forwards
+        * .mark is 'location': to start.  This is not moved.
+        * .mark2, if set, is location to stop.
         * .comm2 is 'consume': pass char mark and report if finished.
         *
+        * comm2 is passed:
+        * .mark - the mark that was passed in and gets moved
+        * .num - char character just before .mark
+        * .str - num utf8 text after mark.  It may not be present
+        *       and if it is, at most .num2 bytes can be used
+        * .num2 - usable length of .str
+        *
+        * comm2 it typically embedded in another struct that can
+        * be accessed in the callback (using container_of in C code).
+        * If the caller need to know where the callback aborted, the
+        * callback need to record that somehow.
+        *
+        * comm2 should return 1 if the main char was consumed,
+        * 1+n if n bytes (not chars) from str were consumed
+        * -ve to abort.
+        *
+        * If the callback processes some of 'str', the mark will no longer
+        * be accurate.  If it needs an accurate mark, it can walk a copy
+        * forward, or return a suitable count and be called again with an
+        * accurate mark.
         */
        struct mark *m = ci->mark;
        struct commcache dchar = CCINIT;
@@ -833,6 +854,7 @@ DEF_CMD(doc_default_content)
 
        if (!m || !ci->comm2)
                return Enoarg;
+       m = mark_dup(m);
        if (strcmp(ci->key, "doc:content-bytes") == 0)
                cmd = "doc:byte";
 
@@ -842,6 +864,7 @@ DEF_CMD(doc_default_content)
               comm_call(ci->comm2, "consume", ci->home, (nxt & 0x1FFFF), m) > 0)
                nxt = ccall(&dchar, cmd, ci->home, 1, m);
 
+       mark_free(m);
        return nxt < 0 ? nxt : 1;
 }
 
@@ -901,7 +924,7 @@ DEF_CMD(doc_get_str)
         */
        int bytes = strcmp(ci->key, "doc:get-bytes") == 0;
        struct getstr g;
-       struct mark *from = NULL, *to = NULL, *m;
+       struct mark *from = NULL, *to = NULL;
 
        if (ci->mark && ci->mark2) {
                if (ci->mark2->seq < ci->mark->seq) {
@@ -917,11 +940,12 @@ DEF_CMD(doc_get_str)
        g.bytes = bytes;
        buf_init(&g.b);
        g.end = to;
-       if (from)
-               m = mark_dup(from);
-       else
-               m = vmark_new(ci->focus, MARK_UNGROUPED, NULL);
-       if (!m)
+       if (!from) {
+               from = vmark_new(ci->focus, MARK_UNGROUPED, NULL);
+               if (from)
+                       call("doc:set-ref", ci->focus, 1, from);
+       }
+       if (!from)
                return Efail;
        if (!to) {
                to = vmark_new(ci->focus, MARK_UNGROUPED, NULL);
@@ -929,8 +953,9 @@ DEF_CMD(doc_get_str)
                        call("doc:set-ref", ci->focus, 0, to);
        }
        call_comm(bytes ? "doc:content-bytes" : "doc:content",
-                 ci->focus, &g.c, 0, m, NULL, 0, to);
-       mark_free(m);
+                 ci->focus, &g.c, 0, from, NULL, 0, to);
+       if (from != ci->mark && from != ci->mark2)
+               mark_free(from);
        if (to != ci->mark && to != ci->mark2)
                mark_free(to);
        comm_call(ci->comm2, "callback:get-str", ci->focus, g.b.len, NULL,
index e637d4bbd7ac40a8fea59eaa9328921b122ebeb4..cf594d175c1cec2cc273bf80146c88dc77c8889d 100644 (file)
@@ -496,7 +496,7 @@ DEF_CMD(mp_content)
 
        if (!ci->mark || !ci->comm2)
                return Enoarg;
-       m = ci->mark;
+       m = mark_dup(ci->mark);
        m2 = ci->mark2;
        cb.last_ret = 1;
        while (cb.last_ret > 0 && m->ref.docnum < mpi->nparts &&
@@ -531,6 +531,7 @@ DEF_CMD(mp_content)
                        post_move(m);
                }
        }
+       mark_free(m);
        return ret;
 }
 
index c7ea8e4479ad206cad73029125e584c5191630c1..ddfa12002daae134e5f7ac48cc232e0ffac5409e 100644 (file)
@@ -529,9 +529,7 @@ DEF_CMD(do_replace)
                                                       NULL, Pattern);
                        if (ptn) {
                                char *new2;
-                               struct mark *tmp = mark_dup(m);
-                               call_comm("doc:content", esi->target, ptn, 0, tmp);
-                               mark_free(tmp);
+                               call_comm("doc:content", esi->target, ptn, 0, m);
                                new2 = comm_call_ret(strsave, ptn, "interp",
                                                     esi->target, 0, NULL, new);
                                if (new2)
index dae03726a758bc53fb968d5c35c2e598807bcc14..382684e1af832a72bff57dead07f1eea9d6631b2 100644 (file)
@@ -145,17 +145,21 @@ DEF_CMD(crop_clip)
 DEF_CMD(crop_content)
 {
        struct crop_data *cd = ci->home->data;
-       struct mark *m2;
+       struct mark *m, *m2;
        int ret;
 
-       crop(ci->mark, cd);
+       if (!ci->mark)
+               return Enoarg;
+       m = mark_dup(ci->mark);
+       crop(m, cd);
        crop(ci->mark2, cd);
        if (ci->mark2)
                m2 = ci->mark2;
        else
                m2 = mark_dup(cd->end);
        ret = home_call_comm(ci->home->parent, ci->key, ci->home,
-                            ci->comm2, 0, ci->mark, NULL, 0, m2);
+                            ci->comm2, 0, m, NULL, 0, m2);
+       mark_free(m);
        if (m2 != ci->mark2)
                mark_free(m2);
        return ret;
index 2b716c58c510a194fedde971858ab1902dc69631..407ecd3b01c7c881f548769316a622b7650d3c18 100644 (file)
@@ -121,7 +121,6 @@ static void do_count(struct pane *p safe, struct pane *owner safe,
 {
        /* if 'end' is NULL, go all the way to EOF */
        struct clcb cl;
-       struct mark *tmp;
 
        cl.lines = 0;
        cl.words = 0;
@@ -139,13 +138,9 @@ static void do_count(struct pane *p safe, struct pane *owner safe,
        *linep = 0;
        *wordp = 0;
        *charp = 0;
-       tmp = mark_dup(start);
-       if (call_comm("doc:content", p, &cl.c, 0, tmp, NULL, 0, end) <= 0 ||
-           (add_marks && cl.add_marks == 0)) {
-               mark_free(tmp);
+       if (call_comm("doc:content", p, &cl.c, 0, start, NULL, 0, end) <= 0 ||
+           (add_marks && cl.add_marks == 0))
                return;
-       }
-       mark_free(tmp);
 
        if (cl.add_marks && cl.start && cl.start != start && cl.chars == 0) {
                mark_free(cl.start);
index 46fee53f8054a6561ecfeed88b57b6c048d8b5d8..da7fa8620072644165d9756eac0daa4145a4f5b4 100644 (file)
@@ -494,17 +494,14 @@ DEF_CB(equal_test)
 DEF_CMD(text_equals)
 {
        struct texteql te;
-       struct mark *m;
 
        if (!ci->str || !ci->mark)
                return Enoarg;
 
-       m = mark_dup(ci->mark);
        te.c = equal_test;
        te.text = ci->str;
        te.matched = False;
-       call_comm("doc:content", ci->focus, &te.c, 0, m);
-       mark_free(m);
+       call_comm("doc:content", ci->focus, &te.c, 0, ci->mark);
        return te.matched ? 1 : Efalse;
 }
 
index bd4487924ce66c605110c1a3d7bd97448fc66802..1e78312132210de029c353f0d14eaa547f549c2b 100644 (file)
@@ -225,8 +225,7 @@ class DiffPane(edlib.Pane):
             return 1
         cmd = focus.call("make-search", ptn,
                          edlib.RXLF_ANCHORED|edlib.RXLF_BACKTRACK, ret='comm')
-        m2 = m.dup()
-        focus.call("doc:content", m2, cmd)
+        focus.call("doc:content", m, cmd)
         f = cmd("getcapture", "len", focus, 1)-1
         if self.which == 0 or self.which > f:
             # get the "after" section
@@ -240,6 +239,7 @@ class DiffPane(edlib.Pane):
         wcmd = focus.call("MakeWiggle", ret='comm')
         if not wcmd:
             return edlib.Efail
+        m2 = m.dup()
         focus.call("doc:EOL", 1, m2, 1)
         m3 = mark.dup()
         focus.call("doc:EOL", -1, m3)
index 7fbaef43d91a05462eaaba0a44faed14967bc235..9727727564c22396ee9dbc522fdab90790285b39 100644 (file)
@@ -89,7 +89,7 @@ class CalcView(edlib.Pane):
                 if c and c == '>':
                     self.getvar("reinit", focus,
                                 edlib.RXLF_ANCHORED | edlib.RXLF_BACKTRACK)
-                    focus.call("doc:content", m.dup(), self.getvar)
+                    focus.call("doc:content", m, self.getvar)
                     nm = self.getvar("interp", focus, "\\1", ret='str')
                     # replace this line
                     focus.call("doc:EOL", 1, m)
index c09d283eee774ab2eb1cba82cf120304f8862cea..f445844d639d6bee54af95bcbe4f12a8aa9f8c5f 100644 (file)
@@ -153,25 +153,28 @@ endwhile:
 
 DEF_CMD(format_content)
 {
+       struct mark *m;
+
        if (!ci->mark || !ci->comm2)
                return Enoarg;
        if (ci->num)
                /* Cannot handle bytes */
                return Einval;
 
-       while (doc_following(ci->focus, ci->mark) != WEOF) {
+       m = mark_dup(ci->mark);
+       while (doc_following(ci->focus, m) != WEOF) {
                const char *l, *c;
                wint_t w;
 
-               l = do_format(ci->focus, ci->mark, NULL, -1, 0);
+               l = do_format(ci->focus, m, NULL, -1, 0);
                if (!l)
                        break;
-               doc_next(ci->focus, ci->mark);
+               doc_next(ci->focus, m);
                c = l;
                while (*c) {
                        w = get_utf8(&c, NULL);
                        if (w >= WERR ||
-                           comm_call(ci->comm2, "consume", ci->focus, w, ci->mark) <= 0)
+                           comm_call(ci->comm2, "consume", ci->focus, w, m) <= 0)
                                /* Finished */
                                break;
                }
@@ -179,6 +182,7 @@ DEF_CMD(format_content)
                if (*c)
                        break;
        }
+       mark_free(m);
        return 1;
 }
 
@@ -673,6 +677,7 @@ DEF_CMD(format_content2)
                /* Cannot handle bytes */
                return Einval;
        set_format(focus, rd);
+       m = mark_dup(m);
 
        pane_set_time(home);
        do {
@@ -776,6 +781,7 @@ DEF_CMD(format_content2)
                 (!end || mark_ordered_or_same(m, end)) &&
                 comm_call(ci->comm2, "consume", ci->focus, nxt, m) > 0);
 
+       mark_free(m);
        return 1;
 }