X-Git-Url: https://git.xinqibao.xyz/st.git/blobdiff_plain/42fa1f5ce46593a9d6c2f9196c1aae1a60ca07d1..215bdb2da3eca77ba01b70503c527baaad67c359:/st.c

diff --git a/st.c b/st.c
index 6bfa834..d22c605 100644
--- a/st.c
+++ b/st.c
@@ -1,4 +1,4 @@
-/* See LICENSE for licence details. */
+/* See LICENSE for license details. */
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -352,6 +352,7 @@ static void draw(void);
 static void redraw(void);
 static void drawregion(int, int, int, int);
 static void execsh(void);
+static void stty(void);
 static void sigchld(int);
 static void run(void);
 
@@ -508,6 +509,7 @@ static char *opt_title = NULL;
 static char *opt_embed = NULL;
 static char *opt_class = NULL;
 static char *opt_font = NULL;
+static char *opt_line = NULL;
 static int oldbutton = 3; /* button event on startup: 3 = release */
 
 static char *usedfont = NULL;
@@ -944,7 +946,7 @@ getsel(void) {
 	ptr = str = xmalloc(bufsize);
 
 	/* append every set & selected glyph to the selection */
-	for(y = sel.nb.y; y < sel.ne.y + 1; y++) {
+	for(y = sel.nb.y; y <= sel.ne.y; y++) {
 		linelen = tlinelen(y);
 
 		if(sel.type == SEL_RECTANGULAR) {
@@ -1253,11 +1255,55 @@ sigchld(int a) {
 	exit(EXIT_SUCCESS);
 }
 
+
+void
+stty(void)
+{
+	char cmd[_POSIX_ARG_MAX], **p, *q, *s;
+	size_t n, siz;
+
+	if((n = strlen(stty_args)) > sizeof(cmd)-1)
+		die("incorrect stty parameters\n");
+	memcpy(cmd, stty_args, n);
+	q = cmd + n;
+	siz = sizeof(cmd) - n;
+	for(p = opt_cmd; p && (s = *p); ++p) {
+		if((n = strlen(s)) > siz-1)
+			die("stty parameter length too long\n");
+		*q++ = ' ';
+		q = memcpy(q, s, n);
+		q += n;
+		siz-= n + 1;
+	}
+	*q = '\0';
+	system(cmd);
+}
+
 void
 ttynew(void) {
 	int m, s;
 	struct winsize w = {term.row, term.col, 0, 0};
 
+	if(opt_io) {
+		term.mode |= MODE_PRINT;
+		iofd = (!strcmp(opt_io, "-")) ?
+			  STDOUT_FILENO :
+			  open(opt_io, O_WRONLY | O_CREAT, 0666);
+		if(iofd < 0) {
+			fprintf(stderr, "Error opening %s:%s\n",
+				opt_io, strerror(errno));
+		}
+	}
+
+	if (opt_line) {
+		if((cmdfd = open(opt_line, O_RDWR)) < 0)
+			die("open line failed: %s\n", strerror(errno));
+		close(STDIN_FILENO);
+		dup(cmdfd);
+		stty();
+		return;
+	}
+
 	/* seems to work fine on linux, openbsd and freebsd */
 	if(openpty(&m, &s, NULL, NULL, &w) < 0)
 		die("openpty failed: %s\n", strerror(errno));
@@ -1267,6 +1313,7 @@ ttynew(void) {
 		die("fork failed\n");
 		break;
 	case 0:
+		close(iofd);
 		setsid(); /* create a new process group */
 		dup2(s, STDIN_FILENO);
 		dup2(s, STDOUT_FILENO);
@@ -1281,16 +1328,6 @@ ttynew(void) {
 		close(s);
 		cmdfd = m;
 		signal(SIGCHLD, sigchld);
-		if(opt_io) {
-			term.mode |= MODE_PRINT;
-			iofd = (!strcmp(opt_io, "-")) ?
-				  STDOUT_FILENO :
-				  open(opt_io, O_WRONLY | O_CREAT, 0666);
-			if(iofd < 0) {
-				fprintf(stderr, "Error opening %s:%s\n",
-					opt_io, strerror(errno));
-			}
-		}
 		break;
 	}
 }
@@ -1576,11 +1613,9 @@ tmoveto(int x, int y) {
 		miny = 0;
 		maxy = term.row - 1;
 	}
-	LIMIT(x, 0, term.col-1);
-	LIMIT(y, miny, maxy);
 	term.c.state &= ~CURSOR_WRAPNEXT;
-	term.c.x = x;
-	term.c.y = y;
+	term.c.x = LIMIT(x, 0, term.col-1);
+	term.c.y = LIMIT(y, miny, maxy);
 }
 
 void
@@ -2451,21 +2486,19 @@ tdectest(char c) {
 
 void
 tstrsequence(uchar c) {
-	if (c & 0x80) {
-		switch (c) {
-		case 0x90:   /* DCS -- Device Control String */
-			c = 'P';
-			break;
-		case 0x9f:   /* APC -- Application Program Command */
-			c = '_';
-			break;
-		case 0x9e:   /* PM -- Privacy Message */
-			c = '^';
-			break;
-		case 0x9d:   /* OSC -- Operating System Command */
-			c = ']';
-			break;
-		}
+	switch (c) {
+	case 0x90:   /* DCS -- Device Control String */
+		c = 'P';
+		break;
+	case 0x9f:   /* APC -- Application Program Command */
+		c = '_';
+		break;
+	case 0x9e:   /* PM -- Privacy Message */
+		c = '^';
+		break;
+	case 0x9d:   /* OSC -- Operating System Command */
+		c = ']';
+		break;
 	}
 	strreset();
 	strescseq.type = c;
@@ -2774,7 +2807,6 @@ tresize(int col, int row) {
 	int i;
 	int minrow = MIN(row, term.row);
 	int mincol = MIN(col, term.col);
-	int slide = term.c.y - row + 1;
 	bool *bp;
 	TCursor c;
 
@@ -2784,20 +2816,19 @@ tresize(int col, int row) {
 		return;
 	}
 
-	/* free unneeded rows */
-	i = 0;
-	if(slide > 0) {
-		/*
-		 * slide screen to keep cursor where we expect it -
-		 * tscrollup would work here, but we can optimize to
-		 * memmove because we're freeing the earlier lines
-		 */
-		for(/* i = 0 */; i < slide; i++) {
-			free(term.line[i]);
-			free(term.alt[i]);
-		}
-		memmove(term.line, term.line + slide, row * sizeof(Line));
-		memmove(term.alt, term.alt + slide, row * sizeof(Line));
+	/*
+	 * slide screen to keep cursor where we expect it -
+	 * tscrollup would work here, but we can optimize to
+	 * memmove because we're freeing the earlier lines
+	 */
+	for(i = 0; i <= term.c.y - row; i++) {
+		free(term.line[i]);
+		free(term.alt[i]);
+	}
+	/* ensure that both src and dst are not NULL */
+	if (i > 0) {
+		memmove(term.line, term.line + i, row * sizeof(Line));
+		memmove(term.alt, term.alt + i, row * sizeof(Line));
 	}
 	for(i += row; i < term.row; i++) {
 		free(term.line[i]);
@@ -3922,17 +3953,13 @@ run(void) {
 	long deltatime;
 
 	/* Waiting for window mapping */
-	while(1) {
+	do {
 		XNextEvent(xw.dpy, &ev);
-		if(XFilterEvent(&ev, None))
-			continue;
 		if(ev.type == ConfigureNotify) {
 			w = ev.xconfigure.width;
 			h = ev.xconfigure.height;
-		} else if(ev.type == MapNotify) {
-			break;
 		}
-	}
+	} while(ev.type != MapNotify);
 
 	ttynew();
 	cresize(w, h);
@@ -4019,14 +4046,16 @@ run(void) {
 
 void
 usage(void) {
-	die("%s " VERSION " (c) 2010-2015 st engineers\n" \
+	die("%s " VERSION " (c) 2010-2015 st engineers\n"
 	"usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
-	"          [-i] [-t title] [-w windowid] [-e command ...]\n", argv0);
+	"          [-i] [-t title] [-w windowid] [-e command ...] [command ...]\n"
+	"       st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
+	"          [-i] [-t title] [-w windowid] [-l line] [stty_args ...]\n",
+	argv0);
 }
 
 int
 main(int argc, char *argv[]) {
-	char *titles;
 	uint cols = 80, rows = 24;
 
 	xw.l = xw.t = 0;
@@ -4041,14 +4070,8 @@ main(int argc, char *argv[]) {
 		opt_class = EARGF(usage());
 		break;
 	case 'e':
-		/* eat all remaining arguments */
-		if(argc > 1) {
-			opt_cmd = &argv[1];
-			if(argv[1] != NULL && opt_title == NULL) {
-				titles = xstrdup(argv[1]);
-				opt_title = basename(titles);
-			}
-		}
+		if(argc > 1)
+			--argc, ++argv;
 		goto run;
 	case 'f':
 		opt_font = EARGF(usage());
@@ -4063,6 +4086,9 @@ main(int argc, char *argv[]) {
 	case 'o':
 		opt_io = EARGF(usage());
 		break;
+	case 'l':
+		opt_line = EARGF(usage());
+		break;
 	case 't':
 		opt_title = EARGF(usage());
 		break;
@@ -4075,6 +4101,12 @@ main(int argc, char *argv[]) {
 	} ARGEND;
 
 run:
+	if(argc > 0) {
+		/* eat all remaining arguments */
+		opt_cmd = argv;
+		if(!opt_title)
+			opt_title = basename(xstrdup(argv[0]));
+	}
 	setlocale(LC_CTYPE, "");
 	XSetLocaleModifiers("");
 	tnew(MAX(cols, 1), MAX(rows, 1));