henesyinit from lsubb0c8bdb6 years agoHistory
438 lines · 7.2 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include <fcall.h>#include <draw.h>#include <mouse.h>#include <cursor.h>#include <keyboard.h>#include <frame.h>#include <9p.h>#include <plumb.h>#include <b.h>#include "gui.h"#include "cook.h"#include <pool.h> static int	creatingcol;static int	creatingrow;static int	deleting;static int	identifying;static int	copying;static File*	movingf; static voidresetcmd(void){	creatingcol = creatingrow = deleting = identifying = copying = 0;	movingf = nil;	argcursor(0);} intwithin(File* d, File* f){	int	found;	File**	w;	File**	l;	File*	fp;	Panel*	np; 	found = 0;	assert(f);	w = newfilewalk(d);	for (l = w; fp = *l; l++)		if (ispanel(fp)){			found |= (fp == f);			np = fp->aux;			if (!found && (np->type == Qcol || np->type == Qrow))				found |= within(fp, f);		}	endfilewalk(w);	return found;} static voidnotifymove(File* f, char* old, int nlen){	File**	l;	File**	w;	File*	fp;	Panel*	p;	char*	npath; 	p = f->aux;	npath = filepath(f);	free(p->path);	p->path = estrdup9p(npath);	conprint(p->con, "%s%s path %s\001", old, npath + nlen, npath);	free(npath);	w = newfilewalk(f);	for (l = w; fp = *l; l++)		if (ispanel(fp))			notifymove(fp, old, nlen);	endfilewalk(w);} static File*insertpoint(File* f, Point xy){	File**	l;	File**	w;	File*	fp;	Panel*	p;	Panel*	np;	File*	last;	int	m;	int	v; 	p = f->aux;	last = nil;	w = newfilewalk(f);	for (l = w; fp = *l; l++){		if (!ispanel(fp))			continue;		np = fp->aux;		if (p->type == Qcol){			m = (np->rect.min.y + np->rect.max.y)/2;			v = xy.y;		} else {			m = (np->rect.min.x + np->rect.max.x)/2;			v = xy.x;		}		if (v < m)			break;		last = fp;	}	endfilewalk(w);	return last;} static voidmovefile(File* from, File* f, Point xy){	Panel* p;	File*	at;	char*	opath;	char*	npath; 	if (within(from, f))		return;	opath = filepath(from->parent);	detachfile(from);	p = f->aux;	if (p->type != Qcol && p->type != Qrow)		f = f->parent;	at = insertpoint(f, xy);	insertfile(from, f, at);	npath = filepath(f);	notifymove(from, opath, strlen(npath));	free(opath);	free(npath);	resize();} static voidmkpanel(int id, File* f){	Panel*	p;	char*	s;	File*	nf; 	p = f->aux;	if (p->type != Qcol && p->type != Qrow){		f = f->parent;		p = f->aux;	}	assert(p->type == Qcol || p->type == Qrow);	s = smprint("%s:%d", (id == Qcol ? "col:" : "row:"), rand());	nf = newfspanel(f, s, f->uid);	p = nf->aux;	p->flags |= Ptag|Playout;	closefile(nf);	free(s);} voidrmpanel(File* f){	File**	l;	File**	w;	File*	fp; 	edprint("rmpanel %s\n", f->name); 	/* Deleting is a dangerous operation.	 * Make sure despite bugs we won't delete on	 * following clicks. Safety first.	 */	deleting = 0; 	incref(f);	w = newfilewalk(f);	for (l = w; fp = *l; l++){		if (fp->qid.type&QTDIR)			rmpanel(fp);		else {			incref(fp);			if (removefile(fp) < 0)				fprint(2, "rmpanel: %r\n");		}	}	endfilewalk(w);	removefile(f);} intintag(Panel* p, Point xy){	int	ht; 	if (p->flags&Pmore)		ht = 2*Taght;	else		ht = Taght;	return ptinrect(xy, Rect(p->rect.min.x, p->rect.min.y,				p->rect.min.x+Tagwid,				p->rect.min.y+ht));} intwcommand(char* c){	char*	s; 	edprint("command: %s\n", c);	if (!strcmp(c, "Col"))		creatingcol = 1;	else if (!strcmp(c, "Row"))		creatingrow = 1;	else if (!strcmp(c, "Sel"))		identifying = 1;	else if (!strcmp(c, "Del"))		deleting = 1;	else if (!strcmp(c, "Arg"))		copying = 1;	else if (!strcmp(c, "Ox")){		sendp(startc, estrdup9p(Ox));		return 1;	} else if (!strncmp(c, "Ox ", 3)){		c += 3;		while(*c == ' ')			c++;		s = smprint("%s %s", Ox, c);		sendp(startc, s);		return 1;	} else		return 0;	argcursor(1);	return 1;} static voidsnarfpath(File* f, char* pref){	Panel*	p;	char*	s; 	p = f->aux;	if (pref)		s=smprint("%s /devs%s", pref, p->path);	else		s=smprint("/devs%s", p->path);	writefstr("/dev/snarf", s);	free(s);} static intplumbexec(char* dir, char* arg){	static int plumbsendfd = -1;	Plumbmsg*m; 	if (plumbsendfd < 0)		plumbsendfd = plumbopen("send", OWRITE|OCEXEC);	if (plumbsendfd < 0){		fprint(2, "plumbopen: send: %r\n");		return 0;	}	m = malloc(sizeof(Plumbmsg));	if (m == nil)		return 0;	m->src = estrdup9p(argv0);	m->dst = estrdup9p("exec");	m->wdir= estrdup9p(dir);	m->type = estrdup9p("text");	m->attr = nil;	m->data = smprint("exec %s", arg);	m->ndata= -1;	assert(m->wdir && m->src && m->data);	if (plumbsend(plumbsendfd, m) < 0){		fprint(2, "plumbexec: %r\n");		plumbfree(m);		return 0;	}	plumbfree(m);	return 1;} static voidcopypath(File* f){	Panel*	p;	char*	s;	char*	cmd; 	p = f->aux;	s = readfstr("/dev/snarf");	cmd = smprint("%s /devs%s", s, p->path);	plumbexec("/", cmd);	free(cmd);	free(s);} voidtagmousecmd(File *f, Cmouse* m, Channel* mc){	Panel*	p;	Panel*	pfp;	File*	nf;	int	innerok; 	p = f->aux;	if (!m->buttons)		return;	innerok = 0;	if (m->buttons == 1){		recv(mc, m);		if (!m->buttons){			if (intag(p, m->xy))			if (p->type == Qcol || p->type == Qrow){				if (p->type == Qcol)					p->type = Qrow;				else					p->type = Qcol;				p->flags |= Predraw;				resize();			}		} else {			if (m->buttons == 3 && intag(p, m->xy)){				do {					recv(mc, m);				} while(m->buttons != 0);				argcursor(1);				snarfpath(f, "Ocp" );				argcursor(0);				return;			}			if (m->buttons == 5){				do {					recv(mc, m);				} while(m->buttons != 0);				argcursor(1);				copypath(f);				argcursor(0);				return;			}		slide:			if (!intag(p, m->xy))				return;			argcursor(1);			if (cookslide(m, mc)){				argcursor(0);				nf = pointinpanel(m->xy, innerok);				if (!innerok)					nf = paneltop(nf);				edprint("move start at %s\n", f->name);				edprint("move end at %s\n", nf->name);				if (nf != f){					pfp = f->parent->aux;					p = nf->aux;					p->flags |= Predraw;					pfp->flags|= Predraw;					movefile(f, nf, m->xy);				}			} else				argcursor(0);		}	} else if (m->buttons == 2 && intag(p, m->xy)){		recv(mc, m);		if (!m->buttons){			maxwin(f);			resize();		} else {			innerok = 1;			goto slide;		}	} else  if (m->buttons == 4 && intag(p, m->xy)){		if (cookclick(m, mc)){			if (!(p->flags&Ptop)){				p->flags |= Phide;				pfp = f->parent->aux;				pfp->flags |= (Pmore|Predraw);				resize();			}		}	}} intmousecmdarg(File* f, Cmouse* m, Channel* mc){	Panel*	p;	char*	s;	char*	ns;	int	istop; 	if (creatingcol || creatingrow || deleting || identifying || copying)	if (m->buttons == 1)	if (cookclick(m, mc)){		f = pointinpanel(m->xy, 1);		if (creatingcol){			resetcmd();			mkpanel(Qcol, f);			resize();			return 1;		}		if (creatingrow){			resetcmd();			mkpanel(Qrow, f);			resize();			return 1;		}		if (deleting){			resetcmd();			p = f->aux;			istop = (p->flags&Ptop);			if (istop)				sysfatal("killed by user");			if ((p->type != Qrow && p->type != Qcol) || hastag(f)){				p = f->parent->aux;				p->flags |= Predraw;				rmpanel(f);			}			resize();			return 1;		}		if (identifying){			resetcmd();			snarfpath(f, nil);			return 1;		}		if (copying){			resetcmd();			p = f->aux;			s = readfstr("/dev/snarf");			ns = smprint("%s /devs%s", s, p->path);			writefstr("/dev/snarf", ns);			free(s);			free(ns);			return 1;		}	}	return 0;}