git.strcat.st

/strcat/ss.git/ - summarytreelogarchive

subject
capture geom from stdin; when no geom specified capture full screen
commit
51455524f6344db108cb1029802b8874026f18d9
date
2026-04-21T13:09:22Z
message
diff
 ss.c | 57 ++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 13 deletions(-)

diff --git a/ss.c b/ss.c
index 04940bf..103a8c4 100644
--- a/ss.c
+++ b/ss.c
@@ -3,6 +3,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 static unsigned long
 lowbit(unsigned long x)
@@ -34,6 +35,8 @@ main(int argc, char **argv)
 	Window root;
 	XImage *img;
 	FILE *f;
+	const char *geom;
+	const char *outpath;
 	unsigned int w;
 	unsigned int h;
 	int x;
@@ -43,13 +46,29 @@ main(int argc, char **argv)
 	int ix;
 	int iy;
 	char tail;
+	char geombuf[128];
 
-	if (argc != 3) {
-	    fprintf(stderr, "usage: ss WIDTHxHEIGHT+X+Y file.ppm\n");
-	    return 1;
-	}
-	if (sscanf(argv[1], "%ux%u+%d+%d%c", &w, &h, &x, &y, &tail) != 4 || w == 0 || h == 0) {
-	    fprintf(stderr, "invalid geometry: %s\n", argv[1]);
+	if (argc == 3) {
+	    geom = argv[1];
+	    outpath = argv[2];
+	} else if (argc == 2) {
+	    size_t n;
+
+	    outpath = argv[1];
+	    if (!isatty(0) && fgets(geombuf, sizeof(geombuf), stdin) != NULL) {
+	        n = 0;
+	        while (geombuf[n] != '\0')
+	            n++;
+	        while (n > 0 && (geombuf[n - 1] == '\n' || geombuf[n - 1] == '\r')) {
+	            geombuf[n - 1] = '\0';
+	            n--;
+	        }
+	        geom = geombuf;
+	    } else {
+	        geom = NULL;
+	    }
+	} else {
+	    fprintf(stderr, "usage: ss WIDTHxHEIGHT+X+Y file.ppm | ss file.ppm < geometry\n");
 	    return 1;
 	}
 	if ((dpy = XOpenDisplay(NULL)) == NULL) {
@@ -59,10 +78,22 @@ main(int argc, char **argv)
 
 	sw = DisplayWidth(dpy, DefaultScreen(dpy));
 	sh = DisplayHeight(dpy, DefaultScreen(dpy));
-	if (x < 0 || y < 0 || x + (int)w > sw || y + (int)h > sh) {
-	    fprintf(stderr, "geometry out of bounds (%dx%d screen)\n", sw, sh);
-	    XCloseDisplay(dpy);
-	    return 1;
+	if (geom != NULL) {
+	    if (sscanf(geom, "%ux%u+%d+%d%c", &w, &h, &x, &y, &tail) != 4 || w == 0 || h == 0) {
+	        fprintf(stderr, "invalid geometry: %s\n", geom);
+	        XCloseDisplay(dpy);
+	        return 1;
+	    }
+	    if (x < 0 || y < 0 || x + (int)w > sw || y + (int)h > sh) {
+	        fprintf(stderr, "geometry out of bounds (%dx%d screen)\n", sw, sh);
+	        XCloseDisplay(dpy);
+	        return 1;
+	    }
+	} else {
+	    x = 0;
+	    y = 0;
+	    w = (unsigned int)sw;
+	    h = (unsigned int)sh;
 	}
 
 	root = DefaultRootWindow(dpy);
@@ -73,9 +104,9 @@ main(int argc, char **argv)
 	    return 1;
 	}
 
-	f = fopen(argv[2], "wb");
+	f = fopen(outpath, "wb");
 	if (f == NULL) {
-	    fprintf(stderr, "failed to open output: %s\n", argv[2]);
+	    fprintf(stderr, "failed to open output: %s\n", outpath);
 	    XDestroyImage(img);
 	    XCloseDisplay(dpy);
 	    return 1;
@@ -92,7 +123,7 @@ main(int argc, char **argv)
 	        rgb[1] = chan(p, img->green_mask);
 	        rgb[2] = chan(p, img->blue_mask);
 	        if (fwrite(rgb, 1, 3, f) != 3) {
-	            fprintf(stderr, "write failed: %s\n", argv[2]);
+	            fprintf(stderr, "write failed: %s\n", outpath);
 	            fclose(f);
 	            XDestroyImage(img);
 	            XCloseDisplay(dpy);