shithub: view

Download patch

ref: fbd2be563dc2460c707017485ca43ce42a5b946d
parent: 47820fc9d475fec74b9dd617241216d686b63316
author: phil9 <telephil9@gmail.com>
date: Wed Nov 24 16:35:27 EST 2021

implement image rotation

	image rotation options are available via menu2.
	It basically pipes the image to rotate(1).

--- a/view.c
+++ b/view.c
@@ -26,16 +26,33 @@
 
 enum
 {
+	Mhflip,
+	Mvflip,
+	Mrotleft,
+	Mrotright,
+};
+char *menu2str[] =
+{
+	"flip horiz.",
+	"flip vert.",
+	"rotate left",
+	"rotate right",
+	nil,
+};
+Menu menu2 = { menu2str };
+
+enum
+{
 	Mopen,
 	Mexit,
 };
-char *menu2str[] =
+char *menu3str[] =
 {
 	"open",
 	"exit",
 	nil,
 };
-Menu menu2 = { menu2str };
+Menu menu3 = { menu3str };
 
 void redraw(void);
 
@@ -219,12 +236,96 @@
 	redraw();
 }
 
+Image*
+rotate(int op)
+{
+	static char *oparg[] = {
+		[Mhflip]	= "-l",
+		[Mvflip]	= "-u",
+		[Mrotleft]	= "-r 270",
+		[Mrotright]	= "-r 90",
+	};
+	Image *i;
+	int ifd[2], ofd[2];
+	char *argv[3] = { "rotate", oparg[op], nil };
+
+	if(pipe(ifd) < 0)
+		return nil;
+	if(pipe(ofd) < 0){
+		close(ifd[0]);
+		close(ifd[1]);
+		return nil;
+	}
+	switch(rfork(RFFDG|RFPROC|RFNOWAIT)){
+	case -1:
+		close(ifd[0]);
+		close(ifd[1]);
+		close(ofd[0]);
+		close(ofd[1]);
+		return nil;
+	case 0:
+		dup(ifd[1], 0);
+		dup(ofd[1], 1);
+		close(ifd[1]);
+		close(ifd[0]);
+		close(ofd[1]);
+		close(ofd[0]);
+		exec("/bin/rotate", argv);
+		_exits("exec");
+	}
+	if(writeimage(ifd[0], img, 1) < 0){
+		i = nil;
+		goto End;
+	}
+	i = readimage(display, ofd[0], 1);
+End:
+	close(ifd[0]);
+	close(ifd[1]);
+	close(ofd[0]);
+	close(ofd[1]);
+	return i;
+}
+
 void
+menu2hit(void)
+{
+	Image *i;
+	int n;
+
+	n = menuhit(2, mctl, &menu2, nil);
+	if(n >= 0){
+		i = rotate(n);
+		freeimage(img);
+		img = i;
+		pos = subpt(ZP, img->r.min);
+		redraw();
+	}
+}
+
+void
+menu3hit(void)
+{
+	char buf[255];
+	int n;
+
+	n = menuhit(3, mctl, &menu3, nil);
+	switch(n){
+	case Mopen:
+		if(enter("open:", buf, sizeof buf, mctl, kctl, nil) > 0){
+			if(loadfromfile(buf) < 0)
+				fprint(2, "cannot open file '%s': %r\n", buf);
+		}
+		break;
+	case Mexit:
+		threadexitsall(nil);
+		break;
+	}
+}
+
+void
 evtmouse(Mouse m)
 {
 	Point o;
-	int n;
-	char buf[255] = {0};
 
 	if(m.buttons == 1){
 		for(;;){
@@ -236,19 +337,10 @@
 			pan(subpt(mctl->xy, o));
 		}
 	}else if(m.buttons == 2){
-		n = menuhit(2, mctl, &menu2, nil);
-		switch(n){
-		case Mopen:
-			if(enter("open:", buf, sizeof buf, mctl, kctl, nil) > 0){
-				if(loadfromfile(buf) < 0)
-					fprint(2, "cannot open file '%s': %r\n", buf);
-			}
-			break;
-		case Mexit:
-			threadexitsall(nil);
-			break;
-		}
-	}
+		menu2hit();
+	}else if(m.buttons == 4){
+		menu3hit();
+	}		
 }
 
 void