* etc).
*
* The middle part has attributes set on the document which can be
- * accessed form the spacer using "multipart-prev:"
+ * accessed from the spacer using "multipart-prev:"
* - email:path identify the part in the nexted multipart struture
* e.g. "header", "body", "body,multipart/mixed:0,mulitpart/alternate:1"
* - email:actions a ':' separated list of buttons. "hide:save:view"
#include <wctype.h>
#include <ctype.h>
#include <stdio.h>
+
+#define PANE_DATA_TYPE struct email_view
+#define DOC_NEXT email_next
+#define DOC_PREV email_prev
#include "core.h"
#include "misc.h"
+struct email_view {
+ int parts;
+ char *invis;
+};
+
+#include "core-pane.h"
+
static inline bool is_orig(int p)
{
return p >= 0 && p % 3 == 0;
static bool cond_append(struct buf *b safe, char *txt safe, char *tag safe,
int offset, int *pos safe)
{
- char *tagf = "active-tag:email-";
+ char *tagf = "action-activate:email-";
int prelen = 1 + strlen(tagf) + strlen(tag) + 1 + 1;
int postlen = 1 + 3;
int len = prelen + strlen(txt) + postlen;
return ret;
}
-DEF_CMD(email_select)
-{
- /* If mark is on a button, press it... */
- struct mark *m = ci->mark;
- char *a, *e, *cmd = NULL;
- wint_t ch;
- int p;
- int b;
-
- if (!m)
- return Enoarg;
- p = get_part(ci->home, m);
- if (!is_spacer(p))
- return Efallthrough;
- ch = doc_following(ci->home, m);
- if (ch == WEOF || !isdigit(ch))
- return 1;
- b = ch - '0';
- a = pane_mark_attr(ci->focus, m, "multipart-prev:email:actions");
- if (!a)
- a = "hide";
- while (b > 0 && a) {
- a = strchr(a, ':');
- if (a)
- a += 1;
- b -= 1;
- }
- if (!a)
- return 1;
- e = strchr(a, ':');
- if (!e)
- e = a + strlen(a);
- asprintf(&cmd, "email:select:%.*s", (int)(e-a), a);
- if (!cmd)
- return Efail;
- return call(cmd, ci->focus, 0, m);
-}
-
DEF_CMD(email_select_hide)
{
int vis = 1;
hdrdoc = call_ret(pane, "doc:multipart:get-part", ci->focus, 1);
if (!headers || !hdrdoc)
return Einval;
- point = vmark_new(hdrdoc, MARK_POINT, NULL);
+ point = point_new(hdrdoc);
if (point) {
char *file;
DEF_LOOKUP_CMD(email_view_handle, email_view_map);
-static char tspecials[] = "()<>@,;:\\\"/[]?=";
+static const char tspecials[] = "()<>@,;:\\\"/[]?=";
static int lws(char c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
0, NULL, NULL, 0, NULL,
"");
if (transformed) {
- m = vmark_new(transformed, MARK_UNGROUPED, NULL);
+ m = mark_new(transformed);
call("doc:set-ref", transformed, 1, m);
call("doc:replace", transformed, 1, m, "01",
0, m, ",markup:func=doc:email:render-image");
* Return 1 if a terminal boundary is found (trailing --)
* Return -1 if nothing is found.
*/
-#define is_lws(c) ({int __c2 = c; __c2 == ' ' || __c2 == '\t' || is_eol(__c2); })
+#define is_lws(c) ({int _c2 = c; _c2 == ' ' || _c2 == '\t' || is_eol(_c2); })
static int find_boundary(struct pane *p safe,
struct mark *start safe, struct mark *end safe,
struct mark *pos,
if (!hdrdoc)
goto out;
call("doc:set:autoclose", hdrdoc, 1);
- point = vmark_new(hdrdoc, MARK_POINT, NULL);
+ point = point_new(hdrdoc);
if (!point)
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");
struct pane *p;
struct mark *point;
- if (ci->str == NULL ||
- strncmp(ci->str, "email:", 6) != 0)
+ if (ci->str == NULL || !strstarts(ci->str, "email:"))
return Efallthrough;
fd = open(ci->str+6, O_RDONLY);
if (fd < 0)
close(fd);
if (!p)
return Efallthrough;
- start = vmark_new(p, MARK_UNGROUPED, NULL);
+ start = mark_new(p);
if (!start) {
pane_close(p);
return Efallthrough;
attr_set_str(&p->attrs, "email:which", "spacer");
call("doc:set:autoclose", p, 1);
spacer = p;
- point = vmark_new(p, MARK_POINT, NULL);
+ point = point_new(p);
call("doc:set-ref", p, 1, point);
call("doc:set-attr", p, 1, point, "markup:func", 0,
NULL, "doc:email:render-spacer");
return Efail;
}
-struct email_view {
- int parts;
- char *invis safe;
-};
-
-DEF_CMD(email_view_free)
+DEF_CMD_CLOSED(email_view_close)
{
struct email_view *evi = ci->home->data;
free(evi->invis);
- unalloc(evi, pane);
+ evi->invis = NULL;
return 1;
}
return cnt;
}
-static int email_step(struct pane *home safe, struct mark *mark safe,
- int forward, int move)
+static inline wint_t email_next(struct pane *p safe, struct mark *m safe,
+ struct doc_ref *r safe, bool bytes)
{
- struct pane *p = home;
struct email_view *evi = p->data;
+ bool move = r == &m->ref;
wint_t ret;
int n = -1;
- if (forward) {
- ret = home_call(p->parent, "doc:char", home,
- move ? 1 : 0,
- mark, evi->invis,
- move ? 0 : 1);
- n = get_part(p->parent, mark);
- if (move && is_spacer(n)) {
- /* Moving in a spacer, If after valid buttons,
- * move to end
- */
- wint_t c;
- unsigned int buttons;
- buttons = count_buttons(p, mark);
- while ((c = doc_following(p->parent, mark)) != WEOF
- && iswdigit(c) && (c - '0') >= buttons)
- doc_next(p->parent, mark);
- }
- } else {
- ret = home_call(p->parent, "doc:char", home,
- move ? -1 : 0,
- mark, evi->invis,
- move ? 0 : -1);
- n = get_part(p->parent, mark);
- if (is_spacer(n) && move &&
- ret != CHAR_RET(WEOF) && iswdigit(ret & 0x1fffff)) {
- /* Just stepped back over the 9 at the end of a spacer,
- * Maybe step further if there aren't 10 buttons.
- */
- unsigned int buttons = count_buttons(p, mark);
- wint_t c = ret & 0x1fffff;
-
- while (c != WEOF && iswdigit(c) && c - '0' >= buttons)
- c = doc_prev(p->parent, mark);
- ret = CHAR_RET(c);
- }
+ ret = home_call(p->parent, "doc:char", p,
+ move ? 1 : 0,
+ m, evi->invis,
+ move ? 0 : 1);
+ n = get_part(p->parent, m);
+ if (move && is_spacer(n)) {
+ /* Moving in a spacer. IF after valid buttons,
+ * move to end.
+ */
+ wint_t c;
+ unsigned int buttons = count_buttons(p, m);
+ while ((c = doc_following(p->parent, m)) != WEOF &&
+ iswdigit(c) && (c-'0') >= buttons)
+ doc_next(p->parent, m);
}
return ret;
}
-DEF_CMD(email_char)
+static inline wint_t email_prev(struct pane *p safe, struct mark *m safe,
+ struct doc_ref *r safe, bool bytes)
{
- struct mark *m = ci->mark;
- struct mark *end = ci->mark2;
- int steps = ci->num;
- int forward = steps > 0;
- int ret = Einval;
+ struct email_view *evi = p->data;
+ bool move = r == &m->ref;
+ wint_t ret;
+ int n = -1;
- if (!m)
- return Enoarg;
- if (end && mark_same(m, end))
- return 1;
- if (end && (end->seq < m->seq) != (steps < 0))
- /* Can never cross 'end' */
- return Einval;
- while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
- ret = email_step(ci->home, m, forward, 1);
- steps -= forward*2 - 1;
+ ret = home_call(p->parent, "doc:char", p,
+ move ? -1 : 0,
+ m, evi->invis,
+ move ? 0 : -1);
+ n = get_part(p->parent, m);
+ if (is_spacer(n) && move &&
+ ret != CHAR_RET(WEOF) && iswdigit(ret & 0x1fffff)) {
+ /* Just stepped back over the 9 at the end of a spacer,
+ * Maybe step further if there aren't 10 buttons.
+ */
+ unsigned int buttons = count_buttons(p, m);
+ wint_t c = ret & 0x1fffff;
+
+ while (c != WEOF && iswdigit(c) && c - '0' >= buttons)
+ c = doc_prev(p->parent, m);
+ ret = c;
}
- if (end)
- return 1 + (forward ? ci->num - steps : steps - ci->num);
- if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
- return ret;
- if (ci->num &&(ci->num2 < 0) == forward)
- return ret;
- /* Want the 'next' char */
- return email_step(ci->home, m, ci->num2 > 0, 0);
+ return ret;
+}
+
+DEF_CMD(email_char)
+{
+ return do_char_byte(ci);
}
DEF_CMD(email_content)
p = to_orig(p);
if (p < 0 || p >= evi->parts)
v = "none";
+ else if (!evi->invis)
+ v = "none";
else if (evi->invis[p] != 'i')
v = "orig";
else if (evi->invis[p+1] != 'i')
return comm_call(ci->comm2, "callback", ci->focus, 0, ci->mark,
v, 0, NULL, ci->str);
}
+ if (strcmp(ci->str, "email:image") == 0) {
+ char im[100];
+
+ p = get_part(ci->home->parent, ci->mark);
+ sprintf(im, "comm:doc:multipart-%d-doc:get-bytes", to_orig(p));
+ return comm_call(ci->comm2, "cb", ci->focus, 0, ci->mark,
+ im, 0, NULL, ci->str);
+ }
return Efallthrough;
}
p = get_part(ci->home->parent, ci->mark);
/* only parts can be invisible, not separators */
p = to_orig(p);
- if (p < 0 || p >= evi->parts)
+ if (p < 0 || p >= evi->parts || !evi->invis)
return Efail;
m1 = mark_dup(ci->mark);
1, m2);
call("view:changed", ci->focus, 0, m1, NULL, 0, m2);
call("Notify:clip", ci->focus, 0, m1, NULL, 0, m2);
- /* for CountLines */
- pane_notify("doc:replaced", ci->home, 0, m1, NULL, 0, m2);
mark_free(m1);
mark_free(m2);
return Efallthrough;
}
-DEF_CMD(email_request)
-{
- /* Someone wants to count lines - attach the line count here,
- * rather than let it fall through to document.
- */
- pane_add_notify(ci->focus, ci->home, ksuffix(ci, "doc:request:"));
- if (strcmp(ci->key, "doc:request:doc:replaced") == 0)
- /* Though for doc:replaced, we want the doc to respond too */
- return Efallthrough;
- return 1;
-}
-
-DEF_CMD(email_countlines)
-{
- return pane_notify(ksuffix(ci, "doc:notify:"),
- ci->home,
- ci->num, ci->mark, ci->str,
- ci->num2, ci->mark2, ci->str2, ci->comm2);
-}
-
-DEF_CMD(status_changed)
-{
- /* line-count sent a status-change message */
- call("doc:status-changed", ci->focus->parent);
- return 1;
-}
-
-DEF_CMD(doc_replaced)
-{
- /* doc sent a doc;replaced message */
- pane_notify("doc:replaced", ci->home,
- ci->num, ci->mark, ci->str,
- ci->num2, ci->mark2, ci->str2, ci->comm2);
- return 1;
-}
-
DEF_CMD(attach_email_view)
{
- struct pane *p;
+ struct pane *p, *p2;
struct email_view *evi;
struct mark *m;
int n, i;
- m = vmark_new(ci->focus, MARK_UNGROUPED, NULL);
+ m = mark_new(ci->focus);
if (!m)
return Efail;
call("doc:set-ref", ci->focus, 0, m);
if (n <= 0 || n > 1000 )
return Einval;
- alloc(evi, pane);
+ p = pane_register(ci->focus, 0, &email_view_handle.c);
+ if (!p)
+ return Efail;
+ evi = p->data;
evi->parts = n;
evi->invis = calloc(n+1, sizeof(char));
for (i = 0; i < n; i++) {
/* Everything else default to invisible */
evi->invis[i] = 'i';
}
- p = pane_register(ci->focus, 0, &email_view_handle.c, evi);
- if (!p) {
- free(evi);
- return Efail;
- }
- /* get doc:replaced from the email so I can pass it to linecount */
- home_call(ci->focus, "doc:request:doc:replaced", p);
- pane_add_notify(p, p, "doc:status-changed");
+ p2 = call_ret(pane, "attach-line-count", p);
+ if (p2)
+ p = p2;
attr_set_str(&p->attrs, "render-hide-CR", "yes");
return comm_call(ci->comm2, "callback:attach", p);
}
static void email_init_map(void)
{
email_view_map = key_alloc();
- key_add(email_view_map, "Free", &email_view_free);
+ key_add(email_view_map, "Close", &email_view_close);
key_add(email_view_map, "doc:char", &email_char);
key_add(email_view_map, "doc:content", &email_content);
key_add(email_view_map, "doc:content-bytes", &email_content);
key_add(email_view_map, "doc:get-attr", &email_view_get_attr);
key_add(email_view_map, "doc:email:render-spacer", &email_spacer);
key_add(email_view_map, "doc:email:render-image", &email_image);
- key_add(email_view_map, "doc:email:select", &email_select);
key_add(email_view_map, "email:select:hide", &email_select_hide);
key_add(email_view_map, "email:select:full", &email_select_full);
key_add(email_view_map, "email:select:extras", &email_select_extras);
- key_add(email_view_map, "doc:request:doc:CountLines", &email_request);
- key_add(email_view_map, "doc:request:doc:replaced", &email_request);
- key_add(email_view_map, "doc:notify:doc:CountLines", &email_countlines);
- key_add(email_view_map, "doc:status-changed", &status_changed);
- key_add(email_view_map, "doc:replaced", &doc_replaced);
}
void edlib_init(struct pane *ed safe)
"open-doc-email");
call_comm("global-set-command", ed, &attach_email_view, 0, NULL,
"attach-email-view");
-
- call("global-load-module", ed, 0, NULL, "lib-html-to-text");
- call("global-load-module", ed, 0, NULL, "lib-html-w3m");
-
- call("global-load-module", ed, 0, NULL, "lib-pdf-to-text");
- call("global-load-module", ed, 0, NULL, "lib-doc-to-text");
- call("global-load-module", ed, 0, NULL, "lib-ical-to-text");
}