]> git.neil.brown.name Git - edlib.git/commitdiff
rfc822header: detect and annotate addresses
authorNeilBrown <neil@brown.name>
Tue, 29 Aug 2023 09:40:44 +0000 (19:40 +1000)
committerNeilBrown <neil@brown.name>
Tue, 29 Aug 2023 09:49:17 +0000 (19:49 +1000)
A "list" is a list of addresses,  find them (between the commas) and add
attributes so their rendering can be controlled.
Each address is associated with length, a tag, and the header type.
The tag can be used to look up the actually address in a pane attribute.

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

index 45e83d3deb5f636974135d8247bf8dafa46aebc6..ca1df7c8afc7880310fd6ab24b0a539b35bf8f1d 100644 (file)
@@ -832,7 +832,7 @@ static bool handle_rfc822(struct pane *email safe,
                goto out;
 
        /* copy some headers to the header temp document */
-       home_call(h2, "get-header", hdrdoc, 0, point, "From", 1);
+       home_call(h2, "get-header", hdrdoc, 0, point, "From", 1, NULL, "list");
        home_call(h2, "get-header", hdrdoc, 0, point, "Date", 1);
        home_call(h2, "get-header", hdrdoc, 0, point, "Subject", 1, NULL, "text");
        home_call(h2, "get-header", hdrdoc, 0, point, "To", 1, NULL, "list");
index 11dbae80d1470c303ff3a5dfde38bb8ca4e11b93..aa72501b89e2ad36a724450fa74db42d1e78a6cb 100644 (file)
@@ -245,6 +245,35 @@ static char *safe charset_word(struct pane *doc safe, struct mark *m safe)
        return last;
 }
 
+static void add_addr(struct pane *p safe, struct mark *m safe,
+                    struct mark *pnt safe, int len,
+                    const char *hdr)
+{
+       char buf[2*sizeof(int)*8/3 + 3 + 20];
+       char *addr;
+       int tag;
+
+       if (len <= 0)
+               return;
+       tag = attr_find_int(p->attrs, "rfc822-addr-cnt");
+       if (tag < 0)
+               tag = 0;
+       tag += 1;
+       snprintf(buf, sizeof(buf), "%d,%d,%s", len, tag, hdr);
+       call("doc:set-attr", p, 1, m,
+            "render:rfc822header-addr", 0, NULL, buf);
+
+       addr = call_ret(str,"doc:get-str", p, 0, m, NULL, 0, pnt);
+       while (addr && utf8_strlen(addr) > len) {
+               int l = utf8_round_len(addr, strlen(addr)-1);
+               addr[l] = 0;
+       }
+       snprintf(buf, sizeof(buf), "addr-%d", tag);
+       attr_set_str(&p->attrs, buf, addr);
+
+       attr_set_int(&p->attrs, "rfc822-addr-cnt", tag);
+}
+
 static void copy_header(struct pane *doc safe,
                        const char *hdr safe, const char *hdr_found safe,
                        const char *type,
@@ -269,6 +298,9 @@ static void copy_header(struct pane *doc safe,
        char attr[100];
        char *a;
        int is_list = type && strcmp(type, "list") == 0;
+       struct mark *istart = NULL;
+       int ilen = 0, isince = 0;
+       bool seen_colon = False;
 
        m = mark_dup(start);
        hstart = mark_dup(point);
@@ -285,10 +317,11 @@ static void copy_header(struct pane *doc safe,
                }
                if (sol && (ch == ' ' || ch == '\t'))
                        continue;
-               if (sol) {
+               if (sol && !(is_list && ilen == 0)) {
                        call("doc:replace", p, 1, NULL, " ", 0, point);
-                       sol = 0;
+                       isince += 1;
                }
+               sol = 0;
                buf[0] = ch;
                buf[1] = 0;
                if (ch == '=' && doc_following(doc, m) == '?')
@@ -298,7 +331,24 @@ static void copy_header(struct pane *doc safe,
                for (i = 0; b[i]; i++)
                        if (b[i] > 0 && b[i] < ' ')
                                b[i] = ' ';
+               if (is_list && seen_colon && !istart && b[0] != ',' &&
+                   (b[0] != ' ' || b[1] != '\0')) {
+                       /* This looks like the start of a list item. */
+                       istart = mark_dup(point);
+                       mark_step(istart, 0);
+                       ilen = isince = 0;
+               }
+               if (b[0] == ':')
+                       seen_colon = True;
                call("doc:replace", p, 1, NULL, b, 0, point);
+               if (ch == ',' && istart) {
+                       add_addr(p, istart, point, ilen, hdr);
+                       mark_free(istart);
+                       istart = NULL;
+               }
+               isince += utf8_strlen(b);
+               if (b[0] != ' ')
+                       ilen = isince;
                if (ch == ',' && is_list) {
                        /* This comma is not in a quoted word, so it really marks
                         * part of a list, and so is a wrap-point.  Consume any
@@ -309,12 +359,21 @@ static void copy_header(struct pane *doc safe,
                        doc_prev(p, p2);
                        while ((ch = doc_following(doc, m)) == ' ')
                                doc_next(doc, m);
+
                        call("doc:replace", p, 1, NULL, " ", 0, point);
                        call("doc:set-attr", p, 1, p2,
                             "render:rfc822header-wrap", 0, NULL, "2");
                        mark_free(p2);
+
+                       istart = mark_dup(point);
+                       mark_step(istart, 0);
+                       ilen = isince = 0;
                }
        }
+       if (istart) {
+               add_addr(p, istart, point, ilen, hdr);
+               mark_free(istart);
+       }
        call("doc:replace", p, 1, NULL, "\n", 0, point);
        snprintf(buf, sizeof(buf), "%zd", strlen(hdr_found)+1);
        call("doc:set-attr", p, 1, hstart, "render:rfc822header", 0, NULL, buf);