shithub: pain

Download patch

ref: 434c6ce50a65ecfdfc4e537edbb2ed4f50da6312
parent: d4bb352f8314035b5b5a2130bd7d93e74d9fec4e
author: jmq <jmq@jmq.sh>
date: Wed Dec 4 01:34:26 EST 2024

lots of shit dude i don't remember

--- a/bindings.c
+++ b/bindings.c
@@ -7,6 +7,7 @@
 #include "fns.h"
 
 Binding * BindingRoot = nil;
+static Point MoveMark = {0};
 
 typedef struct DefaultBinding
 {
@@ -44,14 +45,21 @@
 }
 
 static void
+movecanvas(void)
+{
+	CanvasAt = addpt(CanvasAt, subpt(MousePosition, MoveMark));
+	CanvasMoved = DrawAllLayers = 1;
+}
+
+static void
 BindingMoveCanvas(int e)
 {
-	print("e = %d\n", e);
+	static int movetask = -1;
 	if (e != BEenter)
 		return;
-
-	CanvasAt = addpt(CanvasAt, subpt(MousePosition, PastMousePosition));
-	CanvasMoved = DrawAllLayers = 1;
+	MoveMark = MousePosition;
+	removetask(movetask);
+	movetask = newtask(msec() + 250, movecanvas);
 }
 
 DefaultBinding DefaultBindings[] = 
--- a/dat.h
+++ b/dat.h
@@ -27,6 +27,12 @@
 	void (*func)(int);
 } Binding;
 
+typedef struct Task
+{
+	ulong start;
+	void (*func)(void);
+} Task;
+
 // extern Rectangle CanvasSize = {0};
 // extern Point CanvasAt = {0};
 extern Layer * LayerRoot;
@@ -38,6 +44,7 @@
 extern Point CanvasAt;
 extern int CanvasMoved;
 extern int DrawAllLayers;
+extern ulong LastUpdate;
 // extern Layer * CurrentLayer = nil;
 // extern Image * Background = nil;
 // extern Image * Canvas = nil;
--- a/fns.h
+++ b/fns.h
@@ -2,6 +2,8 @@
 #define RECTANGLE(w, h) ((Rectangle){(Point){(0),(0)}, (Point){(w),(h)}})
 #define NOOP() ((void)(nil))
 #define ARRLEN(a) ((sizeof(a))/(sizeof(a[0])))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
 
 ulong msec(void);
 void setbackground(ulong col);
@@ -13,6 +15,9 @@
 void clearlayer(Layer *);
 void setbrushcolor(ulong col);
 int resizeimage(Image *, Rectangle, int, Image *, Point);
+int newtask(ulong, void (*)(void));
+int removetask(int);
+void runtasks(void);
 
 Point globaltoscreenpt(Point p);
 Point globaltoscreenatcanvaspt(Point p);
--- a/fs.c
+++ b/fs.c
@@ -10,16 +10,27 @@
 #include "dat.h"
 #include "fns.h"
 
+#define WALK1NAMEQID(q_, n_)	\
+if (strcmp(n_, name) == 0) {	\
+	*qid = (Qid){q_, 0, QTDIR};	\
+	return nil;					\
+}
+
+int fillstat(ulong qid, Dir *d);
+
 static void fsopen(Req * req);
 static void fsread(Req * req);
 static void fswrite(Req * req);
 static void fswstat(Req * req);
 static void fscreate(Req * req);
+static void fsattach(Req * req);
 static void fsdestroyfid(Fid * req);
+static void fswalk1(Fid *fid, char *name, Qid *qid);
 static void fsstart(Srv * srv);
 static void fsdetroyfile(File * f);
 
-static char srvpath[128] = {0};
+static char mntpath[128] = {0};
+static void fssrvforker(void (*fn)(void*), void *arg, int flags);
 
 static Srv fs = {
 	.open =			fsopen,
@@ -26,33 +37,184 @@
 	.read =			fsread,
 	.write = 		fswrite,
 	.wstat = 		fswstat,
+	.walk1 =		fswalk1,
 	.create = 		fscreate,
 	.destroyfid = 	fsdestroyfid,
+	.attach =		fsattach,
 	.start = 		fsstart,
+	.forker =		fssrvforker,
 };
 
-static void fsopen(Req * req) {
+enum {
+	Qdir,
+	Qctl,
+	Qcanvas,
+	Qerrors,
+	Qevent,
+	Qcursor,
+	Qwindow,
+	Qlog,
+	Qlabel,
+	Qbrush,
+};
+
+int
+fillstat(ulong qid, Dir *d)
+{
+	static char buf[32];
+
+	nulldir(d);
+	d->type = L'M';
+	d->dev = 1;
+	d->length = 0;
+	d->uid = d->gid = buf;
+	d->muid = "";
+	d->qid = (Qid){qid, drive->nchange, 0};
+	d->atime = time(0);
+	d->mtime = drive->changetime;
+
+	switch(qid){
+	case Qdir:
+		d->name = "/";
+		d->qid.type = QTDIR;
+		d->mode = DMDIR|0777;
+		break;
+
+	case Qctl:
+		d->name = "ctl";
+		d->mode = 0666;
+		break;
+
+	case Qwa:
+		if(drive->writeok == No ||
+		    drive->mmctype != Mmcnone &&
+		    drive->mmctype != Mmccd)
+			return 0;
+		d->name = "wa";
+		d->qid.type = QTDIR;
+		d->mode = DMDIR|0777;
+		break;
+
+	case Qwd:
+		if(drive->writeok == No)
+			return 0;
+		d->name = "wd";
+		d->qid.type = QTDIR;
+		d->mode = DMDIR|0777;
+		break;
+
+	default:
+		if(qid-Qtrack >= drive->ntrack)
+			return 0;
+		t = &drive->track[qid-Qtrack];
+		if(strcmp(t->name, "") == 0)
+			return 0;
+		d->name = t->name;
+		d->mode = t->mode;
+		d->length = t->size;
+		break;
+	}
+	return 1;
+}
+
+static void
+fsopen(Req * req) {
 	respond(req, nil);
 }
-static void fsread(Req * req) {
+
+static void
+fsread(Req * req) {
 	respond(req,nil);
 }
-static void fswrite(Req * req) {
+
+static void
+fswrite(Req * req) {
 	respond(req,nil);
 }
-static void fswstat(Req * req) {
+
+static void
+fswstat(Req * req) {
 	respond(req,nil);
 }
-static void fscreate(Req * req) {
+
+static void
+fscreate(Req * req) {
 	respond(req,nil);
 }
-static void fsdestroyfid(Fid * req) {
+
+static void 
+fswalk1(Fid *fid, char *name, Qid *qid) {
+	switch(fid->qid.path) {
+	case Qdir:
+		if (strcmp("..", name) == 0) {
+			*qid = (Qid){Qdir, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("ctl", name) == 0) {
+			*qid = (Qid){Qdir, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("canvas", name) == 0) {
+			*qid = (Qid){Qcanvas, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("errors", name) == 0) {
+			*qid = (Qid){Qerrors, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("event", name) == 0) {
+			*qid = (Qid){Qevent, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("cursor", name) == 0) {
+			*qid = (Qid){Qcursor, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("window", name) == 0) {
+			*qid = (Qid){Qwindow, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("log", name) == 0) {
+			*qid = (Qid){Qlog, 0, QTDIR};
+			return nil;
+		}
+		if (strcmp("brush", name) == 0) {
+			*qid = (Qid){Qbrush, 0, QTDIR};
+			return nil;
+		}
+		return "file not found";
+	default:
+		return "walk in non-directory";
+	}
+}
+
+static void
+fsdestroyfid(Fid * req) {
 	USED(req);
 }
-static void fsstart(Srv * srv) {
+
+static void
+fsattach(Req * req) {
+	char *spec;
+
+	spec = r->ifcall.aname;
+	if(spec && spec[0]){
+		respond(r, "invalid attach specifier");
+		return;
+	}
+
+	r->ofcall.qid = (Qid){Qdir, 0, QTDIR};
+	r->fid->qid = r->ofcall.qid;
+	respond(r, nil);
+}
+
+static void
+fsstart(Srv * srv) {
 	USED(srv);
 }
-static void fsdestroyfile(File * f) {
+
+static void 
+fsdestroyfile(File * f) {
 	USED(f);
 }
 
@@ -59,28 +221,26 @@
 void
 fsclose(void)
 {
-	if (srvpath[0] == 0)
-		remove(srvpath);
-	srvpath[0] = 0;
+	Waitmsg * m;
+	while ((m = wait()) != nil)
+		free(m);
 }
 
+static void
+fssrvforker(void (*fn)(void*), void *arg, int flags)
+{
+	srvforker(fn, arg, RFPROC|RFNAMEG|RFNOTEG|RFMEM|flags);
+}
+
 int
 fsinit(char * srvname)
 {
-	int rc;
-
-	fs.tree = alloctree(nil, nil, DMDIR|0755, fsdestroyfile);
 	if (fs.tree == nil) {
 		return -1;
 	}
+	snprint(mntpath, sizeof(mntpath), "/mnt/%s", srvname);
+	postmountsrv(&fs, srvname, mntpath, MCREATE|MREPL);
 
-	snprint(srvpath, sizeof(srvpath), "/srv/%s", srvname);
-	remove(srvpath);
-
-	rc = postsrv(&fs, srvname);
-	if (rc == 0) {
-		exits(nil);
-	} else
-		return rc;
+	return 1;
 }
 
--- a/main.c
+++ b/main.c
@@ -16,6 +16,8 @@
 #define RECTOPPT(r, op)	((Rectangle){op(r.min),op(r.max)})
 #define DEFAULTCANVASSIZE RECTANGLE(640, 640)
 #define STROKEEND Endsquare
+#define TASKLISTSIZE 2
+#define ZOOMAPPLYDELAY 250
 
 int CanvasMoved = 1;
 Rectangle CanvasSize;
@@ -24,14 +26,17 @@
 Layer * RootLayer = nil;
 Layer * CurrentLayer = nil;
 Image * Background = nil;
+Image * BorderImage = nil;
 Image * ClearImage = nil;
 int CurrentKeyboard = 0;
 Image * BrushImage = nil;
 Image * ViewImage = nil;
 Image * ZoomedImage = nil;
+Image * OverlayImage = nil;
 ulong LastUpdate = 0;
 int DrawAllLayers = 0;
 int Zoom = 1;
+int TargetZoom = 1;
 int ZoomSensitivity = 1;
 Mouse CurrentMouse = {0};
 Mouse PastMouse = {0};
@@ -38,6 +43,9 @@
 Point MousePosition = {0};
 Point PastMousePosition = {0};
 int RunLoop = 1;
+Task TaskList[TASKLISTSIZE] = {0};
+int ZoomTaskId = -1;
+int DrawOverlay = 0;
 
 Layer *
 newlayer(ulong col)
@@ -102,20 +110,63 @@
 		if (resizeimage(ZoomedImage, vr, Zoom, ViewImage, ZP) < 0)
 			sysfatal("resizeimage: %r");
 	}
+
 	if (CanvasMoved || sr) {
 		draw(screen, screen->r, Background, nil, ZP);
 		draw(screen, RECTOPPT(ZoomedSize, screentoglobalatcanvaspt), ZoomedImage, nil, ZP);
 	}
+
+	if (OverlayImage != nil)
+		draw(screen, OverlayImage->r, OverlayImage, nil, ZP);
+
 	CanvasMoved = 0;
 	DrawAllLayers = 0;
+	DrawOverlay = 0;
 }
 
 ulong
 msec(void)
 {
-	return (ulong)(nsec()/1000);
+	return (ulong)(nsec()/1000000);
 }
 
+int newtask(ulong s, void (*f)(void))
+{
+	uint i;
+	for (i = 0; i < ARRLEN(TaskList); i++) {
+		if (TaskList[i].func != nil)
+			continue;
+
+		TaskList[i] = (Task) { s, f };
+		return i;
+	}
+	
+	return -1;
+}
+
+int removetask(int id)
+{
+	if (id < 0 || id >= ARRLEN(TaskList))
+		return -1;
+	TaskList[id] = (Task) {0, nil};
+	return 0;
+}
+
+void runtasks(void)
+{
+	Task * t;
+	ulong i;
+
+	for (i = 0; i < ARRLEN(TaskList); i++) {
+		t = &TaskList[i];
+		if (t->func == nil || t->start > msec())
+			continue;
+
+		t->func();
+		removetask(i);
+	}
+}
+
 void
 setbackground(ulong col)
 {	
@@ -127,38 +178,65 @@
 		sysfatal("setbackground: %r");
 }
 
-void
-zoom(int z)
+static void
+zoomrect(Rectangle * zs, Point * ca, int z)
 {
 	int osx, osy;
 	Point c;
-
-	if ((Zoom + z) <= 1)
-		Zoom = 1;
-	else
-		Zoom += z;
  
 	c = subpt(CanvasAt, MousePosition);
 	osx = Dx(ZoomedSize);
 	osy = Dy(ZoomedSize);
 
-	ZoomedSize.min = mulpt(CanvasSize.min, Zoom);
-	ZoomedSize.max = mulpt(CanvasSize.max, Zoom);
-	
-	if (ZoomedImage != nil) {
-		freeimage(ZoomedImage);
-		ZoomedImage = nil;
-	}
+	zs->min = mulpt(CanvasSize.min, z);
+	zs->max = mulpt(CanvasSize.max, z);
 
-	CanvasAt = addpt(
+	*ca = addpt(
 		Pt(Dx(ZoomedSize)*c.x/osx, Dy(ZoomedSize)*c.y/osy), 
 		MousePosition
 	);
+}
 
+static void
+applyzoom(void)
+{
+	Zoom = TargetZoom;
+	zoomrect(&ZoomedSize, &CanvasAt, Zoom);
+	if (ZoomedImage != nil) {
+		freeimage(ZoomedImage);
+		ZoomedImage = nil;
+	}
+
  	DrawAllLayers = 1;
+	ZoomTaskId = -1;
 }
 
 void
+zoom(int z)
+{
+	Rectangle zs;
+	Point ca;
+
+	if ((TargetZoom + z) <= 1)
+		TargetZoom = 1;
+	else
+		TargetZoom += z;
+
+	zoomrect(&zs, &ca, TargetZoom);
+	if (OverlayImage != nil) {
+// 		zs = rectaddpt(zs, ca);
+// 		border(OverlayImage, zs, 2, BorderImage, ZP);
+		DrawOverlay = 1;
+	}
+
+	removetask(ZoomTaskId);
+	if ((ZoomTaskId = newtask(msec() + ZOOMAPPLYDELAY, applyzoom)) < 0) {
+		werrstr("newtask: no tasks available");
+		return;
+	}
+}
+
+void
 movecanvas()
 {
 }
@@ -283,6 +361,15 @@
 	}
 }
 
+void
+setoverlaysize(Rectangle r)
+{
+	if (OverlayImage != nil)
+		freeimage(OverlayImage);
+	OverlayImage = allocimage(display, r, RGBA32, 1, DTransparent);
+	DrawOverlay = 1;
+}
+
 static void
 handlekeyboard(int kbdc)
 {
@@ -311,7 +398,7 @@
 void
 main(int argc, char * argv[])
 {
-	int d;
+	ulong d;
 	Event e;
 
 	USED(argc);
@@ -320,25 +407,34 @@
 	if (initdraw(nil, nil, "pain") < 0)
 		sysfatal("initdraw: %r\n");
 
-	if (fsinit("pain") < 1)
-		sysfatal("fsinit: %r");
+// 	if (fsinit(nil) < 1)
+// 		sysfatal("fsinit: %r");
 
-	if (!atexit(fsclose))
-		sysfatal("atexit: %r");
-	
+// 	if (!atexit(fsclose))
+// 		sysfatal("atexit: %r");
+
+	if ((BorderImage = allocimage(display, RECTANGLE(1, 1), RGBA32, 1, DBlack)) == nil)
+		sysfatal("allocimage: %r");
+
+	setoverlaysize(screen->r);
 	CanvasSize = ZoomedSize = DEFAULTCANVASSIZE;
 	setcanvassize(DEFAULTCANVASSIZE);
 	newlayer(DEFAULTLAYERCOLOR);
-	zoom(0);
+	applyzoom();
 	setdefaultbindings();
 
 	einit(Emouse | Ekeyboard);
 	drawcanvas();
 	for(;RunLoop;) {
-		d = msec()-LastUpdate;
-	 	if (d <= UPDATEPERIOD)
-	 		sleep(d - UPDATEPERIOD);
-
+		d = msec();
+		if (d < LastUpdate)
+			LastUpdate = 0;
+		
+		d -= LastUpdate;
+	 	if (d < UPDATEPERIOD)
+	 		sleep(UPDATEPERIOD - d);
+		
+		runtasks();
 		switch (event(&e))
 		{
 		case Ekeyboard: 
--- a/mkfile
+++ b/mkfile
@@ -3,7 +3,6 @@
 TARG=pain
 OFILES=			\
 	main.$O 	\
-	fs.$O		\
 	resize.$O	\
 	bindings.$O	\
 	utils.$O
--