396 lines · 6.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <draw.h>#include <mouse.h>#include <keyboard.h>#include <thread.h>#include <plumb.h>#include "theme.h"#include "kbd.h"#include "a.h" enum{	Padding = 4,}; enum{	Emouse,	Eresize,	Ekeyboard,	Eseemail,	Eshowmesg,	Eselmesg,}; enum{	BACK,	TEXT,	BORD,	PBRD,	PBCK,	NCOLS,}; Mousectl *mctl;Kbdctl *kctl;Channel *showc;Channel *selc;Channel *eventc;Channel *loadc;Mailbox *mboxes[16];int nmboxes;char *mbmenustr[16] = {0};Menu mbmenu = { mbmenustr };Mailbox *mbox;static Image *cols[NCOLS];Rectangle headr;Rectangle indexr;Rectangle pagerr;int collapsed = 0; voiddrawheader(void){	char buf[255] = {0};	Point p; 	draw(screen, headr, cols[BACK], nil, ZP);	p = headr.min;	p.x += Padding;	p.y += Padding / 2;	if(mbox->unseen > 0)		snprint(buf, sizeof buf, "» %s [total:%d - new:%d]", mbox->name, mbox->count, mbox->unseen);	else		snprint(buf, sizeof buf, "» %s [total:%d]", mbox->name, mbox->count);	string(screen, p, cols[TEXT], ZP, font, buf);	line(screen, Pt(headr.min.x, headr.max.y), headr.max, 0, 0, 0, cols[BORD], ZP);} voidredraw(void){	draw(screen, screen->r, cols[BACK], nil, ZP);	drawheader();	indexdraw();	if(collapsed){		line(screen, Pt(indexr.min.x, indexr.max.y), indexr.max, 0, 0, 0, cols[BORD], ZP);		pagerdraw();	}	flushimage(display, 1);} voidresize(void){	headr = screen->r;	headr.max.y = headr.min.y+Padding+font->height;	indexr = screen->r;	indexr.min.y = headr.max.y + 1;	indexr = indexresize(indexr, collapsed);	if(collapsed){		pagerr = screen->r;		pagerr.min.y = indexr.max.y + 1;		pagerresize(pagerr);	}	redraw();} voidloadproc(void *v){	Channel *c; 	c = v;	mboxload(mbox, c);} voiddrawprogress(Rectangle r, Rectangle pr){	draw(screen, pr, cols[PBCK], nil, ZP);	border(screen, r, 2, cols[PBRD], ZP);		flushimage(display, 1);} voidloadmbox(void){	ulong total, count, n;	Point sp, p;	Rectangle r, pr;	int pc;	char buf[255] = {0}; 	draw(screen, screen->r, cols[BACK], nil, ZP);	p.x = (Dx(screen->r)-200)/2;	p.y = (Dy(screen->r)-25)/2;	r = rectaddpt(rectaddpt(Rect(0, 0, 200, 25), p), screen->r.min);	snprint(buf, sizeof buf, "Loading %s...", mbox->name);	sp.x = (Dx(screen->r)-stringwidth(font, buf))/2;	sp.y = r.min.y - font->height - 12 - screen->r.min.y;	string(screen, addpt(screen->r.min, sp), cols[TEXT], ZP, font, buf);	replclipr(screen, 1, insetrect(r, -2));	loadc = chancreate(sizeof(ulong), 1);	proccreate(loadproc, loadc, 8192);	total = recvul(loadc);	count = 0;	for(;;){		n = recvul(loadc);		if(n == 0)			break;		count += 1;		pc = 200*((double)count/total);		pr = rectaddpt(rectaddpt(Rect(0, 0, pc, 25), p), screen->r.min);		if(count % (total/100) == 0)			drawprogress(r, pr);	}	chanfree(loadc);	replclipr(screen, 1, screen->r);} voidswitchmbox(int n){	if(mbox==mboxes[n])		return;	mbox = mboxes[n];	if(!mbox->loaded)		loadmbox();	indexswitch(mbox);	collapsed = 0;	resize();} voidmouse(Mouse m){	int n; 	if(ptinrect(m.xy, headr) && m.buttons==4){		n = menuhit(3, mctl, &mbmenu, nil);		if(n >= 0)			switchmbox(n);		return;	}	indexmouse(m);	if(collapsed)		pagermouse(m);} voidkey(Key k){	if(k.k == Kdel)		threadexitsall(nil);	else if(k.k == 'q'){		if(collapsed){			collapsed = 0;			resize();		}else			threadexitsall(nil);	}else if(k.mods == Malt){		if(collapsed)			pagerkey(k.k);	}else		indexkey(k.k);} voidseemail(Mailevent e){	Mailbox *mb;	char *s;	int i; 	for(mb = nil, i = 0; i < nmboxes; i++){		if(strncmp(mboxes[i]->path, e.path, strlen(mboxes[i]->path))==0){			mb = mboxes[i];			break;		}	}	if(mb==nil)		return;	s = e.path;	switch(e.type){		case Enew:			i = mboxadd(mb, s);			if(mb==mbox){				indexadded(i);				redraw();			}			break;		case Edelete:			i = mboxdel(mb, s);			if(mb==mbox){				indexremoved(i);				redraw();			}			break;		case Emodify:			i = mboxmod(mb, s);			if(i >= 0 && mb==mbox)				redraw();			break;	}	free(s);} voidinit(Channel *selc){	Theme *theme;	Rectangle r; 	theme = loadtheme();	if(theme != nil){		cols[BACK] = theme->back;		cols[TEXT] = theme->text;		cols[BORD] = theme->title;		cols[PBRD] = theme->menubord;		cols[PBCK] = theme->menuback;	}else{		r = Rect(0, 0, 1, 1);		cols[BACK] = allocimage(display, r, screen->chan, 1, 0xFFFFFFFF);		cols[TEXT] = allocimage(display, r, screen->chan, 1, 0x000000FF);		cols[BORD] = allocimage(display, r, screen->chan, 1, DGreygreen);		cols[PBRD] = allocimage(display, r, screen->chan, 1, 0x88CC88FF);		cols[PBCK] = allocimage(display, r, screen->chan, 1, 0xEAFFEAFF);		/*		cols[BACK] = allocimage(display, r, screen->chan, 1, 0x282828FF);		cols[TEXT] = allocimage(display, r, screen->chan, 1, 0xA89984FF);		cols[BORD] = allocimage(display, r, screen->chan, 1, 0x98971AFF);		*/	}	indexinit(mctl, showc, selc, theme);	pagerinit(mctl, kctl, theme);} voidplumbmsg(Message *m){	int fd; 	fd = plumbopen("send", OWRITE|OCEXEC);	if(fd<0)		return;	plumbsendtext(fd, "mongrel", nil, nil, m->path);	close(fd);} voidshowmsg(Message *m){	if(collapsed == 0){		collapsed = 1;		resize();	}	pagershow(m);	if(mesgmarkseen(mbox, m))		redraw();} voidselchanged(Message *m){	if(collapsed == 0)		return;	showmsg(m);}  voidusage(void){	fprint(2, "usage: %s [-m maildir]\n", argv0);	exits("usage");} voidthreadmain(int argc, char *argv[]){	Mouse m;	Key k;	Mailevent e;	Message *msg;	Alt alts[] = 	{		{ nil, &m,   CHANRCV },		{ nil, nil,  CHANRCV },		{ nil, &k,   CHANRCV },		{ nil, &e,   CHANRCV },		{ nil, &msg, CHANRCV },		{ nil, &msg, CHANRCV },		{ nil, nil,  CHANEND },	};	char *s; 	nmboxes = 0;	ARGBEGIN{	case 'm':		s = EARGF(usage());		mboxes[nmboxes] = mboxinit(s);		mbmenustr[nmboxes] = mboxes[nmboxes]->name;		nmboxes++;		break;	default:		fprint(2, "unknown flag '%c'\n", ARGC());		usage();	}ARGEND	if(nmboxes==0){		fprint(2, "no maildir specified\n");		usage();	}	tmfmtinstall();	if(initdraw(nil, nil, "mongrel")<0)		sysfatal("initdraw: %r");	display->locking = 0;	if((mctl = initmouse(nil, screen)) == nil)		sysfatal("initmouse: %r");	if((kctl = initkbd()) == nil)		sysfatal("initkbd: %r");	if((eventc = chancreate(sizeof(Mailevent), 0))==nil)		sysfatal("chancreate: %r");	if((showc = chancreate(sizeof(Message*), 1))==nil)		sysfatal("chancreate: %r");	if((selc = chancreate(sizeof(Message*), 1))==nil)		sysfatal("chancreate: %r");	alts[0].c = mctl->c;	alts[1].c = mctl->resizec;	alts[2].c = kctl->c;	alts[3].c = eventc;	alts[4].c = showc;	alts[5].c = selc;	proccreate(seemailproc, eventc, 8192);	init(selc);	switchmbox(0);	resize();	for(;;){		switch(alt(alts)){		case Emouse:			mouse(m);			break;		case Eresize:			if(getwindow(display, Refnone)<0)				sysfatal("cannot reattach: %r");			resize();			break;		case Ekeyboard:			key(k);			break;		case Eseemail:			seemail(e);			break;		case Eshowmesg:			showmsg(msg);			break;		case Eselmesg:			//plumbmsg(msg);			selchanged(msg);			break;		}	}}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t