ref: 371fe66160a278041a25c39162a4bbcd4e0cc333
dir: /pager.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <mouse.h> #include <keyboard.h> #include <thread.h> #include <plumb.h> #include "theme.h" #include "a.h" #include "w.h" enum { Padding = 4, }; static Mousectl *mc; static Text text; static Rectangle viewr; static Rectangle headr; static Rectangle partsr; static Rectangle textr; static Image *cols[NCOLS]; static Image *headercol; static Message *mesg; static Tzone *tz; static int showcc; static Message *parts[16]; static int nparts; char* findtextpart(Message *m) { Message *p; int i; if(strncmp(m->type, "multipart/", 10) == 0){ for(i = 0; i < m->parts->nelts; i++){ p = m->parts->elts[i]; if(strcmp(p->type, "text/plain") == 0) return p->body; else if(strncmp(p->type, "multipart/", 10) == 0) return findtextpart(p); } } return m->body; } void collectparts(Message *m) { Message *p; int i; if(m->parts == nil) return; for(i = 0; i < m->parts->nelts; i++){ p = m->parts->elts[i]; if(strncmp(p->type, "multipart/", 10) == 0) collectparts(p); else{ if(strcmp(p->type, "text/plain") == 0) continue; parts[nparts++] = p; } } } void pagershow(Message *m) { char *body; int needresize; int oldnparts; oldnparts = nparts; needresize = 0; mesg = m; if(showcc){ if(mesg->cc == nil || mesg->cc[0] == 0){ showcc = 0; needresize = 1; } }else{ if(mesg->cc != nil && mesg->cc[0] != 0){ showcc = 1; needresize = 1; } } mesgloadbody(mesg); nparts = 0; collectparts(mesg); if(nparts != oldnparts) needresize = 1; if(needresize) pagerresize(viewr); body = findtextpart(mesg); textset(&text, body, strlen(body)); pagerdraw(); } static Point drawheader(Point p, char *h, char *s) { Rune r; p = string(screen, p, cols[BORD], ZP, font, h); while(s && *s){ s += chartorune(&r, s); p = runestringn(screen, p, cols[TEXT], ZP, font, &r, 1); } return p; } Point drawparts(Point p) { Point q; int i; for(i = 0; i < nparts; i++){ // q = string(screen, p, cols[TEXT], ZP, font, "=> "); q = p; if(parts[i]->filename != nil && parts[i]->filename[0] != 0) q = string(screen, q, cols[TEXT], ZP, font, parts[i]->filename); else q = string(screen, q, cols[TEXT], ZP, font, "unnamed"); q = string(screen, q, cols[BORD], ZP, font, " ["); q = string(screen, q, cols[BORD], ZP, font, parts[i]->type); string(screen, q, cols[BORD], ZP, font, "]"); p.y += font->height + Padding; } return p; } void pagerdraw(void) { Point p, q; char buf[32], *s; Rune r; Tm t; int w; draw(screen, viewr, cols[BACK], nil, ZP); if(mesg != nil){ p = addpt(headr.min, Pt(Padding, Padding)); tmtime(&t, mesg->time, tz); snprint(buf, sizeof buf, "%τ", tmfmt(&t, "DD/MM/YYYY hh:mm")); w = stringwidth(font, buf); string(screen, addpt(p, Pt(Dx(headr) - w - 2*Padding, 0)), cols[TEXT], ZP, font, buf); q = drawheader(p, " From ", mesg->sender); if(strcmp(mesg->sender, mesg->from) != 0){ q = string(screen, q, cols[TEXT], ZP, font, " <"); s = mesg->from; while(s && *s){ s += chartorune(&r, s); q = runestringn(screen, q, cols[TEXT], ZP, font, &r, 1); } string(screen, q, cols[TEXT], ZP, font, ">"); } p.y += font->height + Padding; drawheader(p, " To ", mesg->to); if(showcc){ p.y += font->height + Padding; drawheader(p, " Cc ", mesg->cc); } p.y += font->height + Padding; drawheader(p, "Subject ", mesg->subject); } line(screen, addpt(headr.min, Pt(0, Dy(headr))), headr.max, 0, 0, 0, headercol, ZP); if(nparts > 0){ p = addpt(partsr.min, Pt(Padding, Padding)); drawparts(p); line(screen, addpt(partsr.min, Pt(0, Dy(partsr))), partsr.max, 0, 0, 0, headercol, ZP); } textdraw(&text); } void pagerresize(Rectangle r) { int n; n = showcc ? 4 : 3; viewr = r; headr = viewr; headr.max.y = headr.min.y + Padding + n*(font->height + Padding); if(nparts > 0){ partsr = viewr; partsr.min.y = headr.max.y + 1; partsr.max.y = partsr.min.y + nparts*(font->height + Padding) + Padding; } textr = viewr; if(nparts > 0) textr.min.y = partsr.max.y + 1; else textr.min.y = headr.max.y + 1; textresize(&text, textr); } void partclick(Point p) { Message *m; char *dst, buf[1024] = {0}; int fd, n; fd = plumbopen("send", OWRITE); if(fd < 0) return; n = (p.y - partsr.min.y) / (font->height+Padding); if(n < 0 || n >= nparts){ close(fd); return; } m = parts[n]; dst = nil; if(strcmp(m->type, "text/html") == 0){ snprint(buf, sizeof buf, "file://%s/body.html", m->path); dst = "web"; }else if(strncmp(m->type, "image/", 6) == 0){ snprint(buf, sizeof buf, "%s/body.%s", m->path, m->type+6); dst = "image"; }else{ snprint(buf, sizeof buf, "%s/body", m->path); } plumbsendtext(fd, "mongrel", dst, nil, buf); close(fd); } void pagermouse(Mouse m) { if(!ptinrect(m.xy, viewr)) return; if(nparts > 0 && ptinrect(m.xy, partsr) && m.buttons == 4) partclick(m.xy); else if(ptinrect(m.xy, textr)) textmouse(&text, mc); } void pagerkey(Rune k) { textkeyboard(&text, k); } void pagerinit(Mousectl *mctl, Theme *theme) { Rectangle r; mc = mctl; tz = tzload("local"); showcc = 0; nparts = 0; if(theme != nil){ cols[BACK] = theme->back; cols[BORD] = theme->border; cols[TEXT] = theme->text; cols[HTEXT] = theme->htext; cols[HIGH] = theme->high; headercol = theme->title; }else{ r = Rect(0, 0, 1, 1); cols[BACK] = display->white; cols[BORD] = allocimage(display, r, screen->chan, 1, 0x999999FF); cols[TEXT] = allocimage(display, r, screen->chan, 1, 0x000000FF); cols[HTEXT] = allocimage(display, r, screen->chan, 1, 0x000000FF); cols[HIGH] = allocimage(display, r, screen->chan, 1, 0xCCCCCCFF); headercol = allocimage(display, r, screen->chan, 1, DGreygreen); } textinit(&text, screen, screen->r, font, cols); }