This patch allows sdiff to auto-detect tty width,
by passing -w auto

More importantly, sdiff will adjust its variables on the fly for
subsequent lines (I don't know if redrawing the current
lines when the tty changes is advisable).

It's pretty straightforward, tested thru sysmerge.

Doesn't seem it's standardized anywhere, I'm not sure having a functionality 
that's
not in gnu-sdiff would be an issue ?


Index: sdiff.c
===================================================================
RCS file: /cvs/src/usr.bin/sdiff/sdiff.c,v
retrieving revision 1.37
diff -u -p -r1.37 sdiff.c
--- sdiff.c     28 Sep 2018 18:21:52 -0000      1.37
+++ sdiff.c     11 Dec 2019 16:42:25 -0000
@@ -17,12 +17,14 @@
 #include <getopt.h>
 #include <limits.h>
 #include <paths.h>
+#include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <util.h>
+#include <sys/ioctl.h>
 
 #include "common.h"
 #include "extern.h"
@@ -43,7 +45,9 @@ struct diffline {
 };
 
 static void astrcat(char **, const char *);
+static void compute_width(void);
 static void enqueue(char *, char, char *);
+static void find_width(void);
 static char *mktmpcpy(const char *);
 static void freediff(struct diffline *);
 static void int_usage(void);
@@ -55,12 +59,16 @@ static void printd(FILE *, size_t);
 static void println(const char *, const char, const char *);
 static void processq(void);
 static void prompt(const char *, const char *);
+static void recompute_width(void);
 __dead static void usage(void);
+static void window_changed(int);
 static char *xfgets(FILE *);
 
 SIMPLEQ_HEAD(, diffline) diffhead = SIMPLEQ_HEAD_INITIALIZER(diffhead);
 size_t  line_width;    /* width of a line (two columns and divider) */
 size_t  width;         /* width of each column */
+size_t  wflag = WIDTH;
+volatile sig_atomic_t got_signal = 0;
 size_t  file1ln, file2ln;      /* line number of file1 and file2 */
 int     Iflag = 0;     /* ignore sets matching regexp */
 int     lflag;         /* print only left column for identical lines */
@@ -153,11 +161,47 @@ FAIL:
        exit(2);
 }
 
+static void
+window_changed(int sig __attribute__((__unused__)))
+{
+       got_signal = 1;
+}
+
+static void
+find_width(void)
+{
+       struct winsize ws;
+
+       if (ioctl(0, TIOCGWINSZ, &ws) != 0) {
+               wflag = WIDTH;
+               signal(SIGWINCH, SIG_DFL);
+       } else
+               wflag = ws.ws_col;
+}
+
+static void
+recompute_width(void)
+{
+       find_width();
+       compute_width();
+}
+
+static void
+compute_width(void)
+{
+       /* Subtract column divider and divide by two. */
+       width = (wflag - 3) / 2;
+       /* Make sure line_width can fit in size_t. */
+       if (width > (SIZE_MAX - 3) / 2)
+               errx(2, "width is too large: %zu", width);
+       line_width = width * 2 + 3;
+}
+
 int
 main(int argc, char **argv)
 {
        FILE *diffpipe, *file1, *file2;
-       size_t diffargc = 0, wflag = WIDTH;
+       size_t diffargc = 0;
        int ch, fd[2], status;
        pid_t pid;
        const char *outfile = NULL;
@@ -236,6 +280,11 @@ main(int argc, char **argv)
                        diffargv[diffargc++] = "-w";
                        break;
                case 'w':
+                       if (strcmp(optarg, "auto") == 0) {
+                               signal(SIGWINCH, window_changed);
+                               find_width();
+                               break;
+                       }
                        wflag = strtonum(optarg, WIDTH_MIN,
                            INT_MAX, &errstr);
                        if (errstr)
@@ -273,7 +322,7 @@ main(int argc, char **argv)
                if (unveil(_PATH_BSHELL, "x") == -1)
                        err(2, "unveil");
        }
-       if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1)
+       if (pledge("stdio rpath wpath cpath proc exec tty", NULL) == -1)
                err(2, "pledge");
 
        /*
@@ -302,12 +351,7 @@ main(int argc, char **argv)
        /* Add NULL to end of array to indicate end of array. */
        diffargv[diffargc++] = NULL;
 
-       /* Subtract column divider and divide by two. */
-       width = (wflag - 3) / 2;
-       /* Make sure line_width can fit in size_t. */
-       if (width > (SIZE_MAX - 3) / 2)
-               errx(2, "width is too large: %zu", width);
-       line_width = width * 2 + 3;
+       compute_width();
 
        if (pipe(fd))
                err(2, "pipe");
@@ -522,6 +566,11 @@ static void
 println(const char *s1, const char div, const char *s2)
 {
        size_t col;
+
+       if (got_signal) {
+               got_signal = 0;
+               recompute_width();
+       }
 
        /* Print first column.  Skips if s1 == NULL. */
        col = 0;

Reply via email to