shithub: neatroff

Download patch

ref: 52bd1c9b13849dd92d9e3619bcf0a89d4067f849
parent: d6629cca62b8f16e016c42e644907404319650e9
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Nov 21 16:21:04 EST 2012

ren: implement \s and \f

--- a/out.c
+++ b/out.c
@@ -50,8 +50,10 @@
 	}
 }
 
-static char *escarg(char *s, char *d)
+static char *escarg(char *s, char *d, int cmd)
 {
+	if (cmd == 's' && (*s == '-' || *s == '+'))
+		*d++ = *s++;
 	if (*s == '(') {
 		s++;
 		*d++ = *s++;
@@ -64,6 +66,8 @@
 			s++;
 	} else {
 		*d++ = *s++;
+		if (cmd == 's' && s[-1] >= '1' && s[-1] <= '3' && isdigit(*s))
+			*d++ = *s++;
 	}
 	*d = '\0';
 	return s;
@@ -74,7 +78,6 @@
 	struct glyph *g;
 	char c[LLEN];
 	char arg[LINELEN];
-	int o_blank = 0;
 	printf("v%d\n", n_v);
 	printf("H%d\n", n_o + n_i);
 	while (*s) {
@@ -84,8 +87,8 @@
 			if (c[0] == '(') {
 				s = utf8get(c, s);
 				s = utf8get(c + strlen(c), s);
-			} else if (strchr("sf", c[0])) {
-				s = escarg(s, arg);
+			} else if (strchr("sfh", c[0])) {
+				s = escarg(s, arg, c[0]);
 				if (c[0] == 's') {
 					out_ps(tr_int(arg, o_s, '\0'));
 					continue;
@@ -94,21 +97,20 @@
 					out_ft(dev_font(arg));
 					continue;
 				}
+				if (c[0] == 'h') {
+					printf("h%d", tr_int(arg, 0, 'm'));
+					continue;
+				}
 			}
 		}
 		g = dev_glyph(c, o_f);
 		if (g) {
-			if (o_blank)
-				printf("h%d", charwid(dev_spacewid(), o_s));
 			if (utf8len(c[0]) == strlen(c)) {
 				printf("c%s%s", c, c[1] ? "\n" : "");
 			} else {
 				printf("C%s\n", c);
 			}
-			printf("h%d", charwid(g->wid, o_s));
-			o_blank = 0;
-		} else {
-			o_blank = 1;
 		}
+		printf("h%d", charwid(g ? g->wid : dev_spacewid(), o_s));
 	}
 }
--- a/ren.c
+++ b/ren.c
@@ -16,16 +16,20 @@
 static struct word words[LINELEN];	/* words in the buffer */
 static int nwords;
 static int wid;				/* total width of the buffer */
+static int ren_backed = -1;		/* pushed back character */
 
 static int ren_next(void)
 {
-	int c = tr_next();
-	if (c < 0)
-		return -1;
-	buf[buflen++] = c;
+	int c = ren_backed >= 0 ? ren_backed : tr_next();
+	ren_backed = -1;
 	return c;
 }
 
+static void ren_back(int c)
+{
+	ren_backed = c;
+}
+
 static int nextchar(char *s)
 {
 	int c = ren_next();
@@ -48,6 +52,7 @@
 static void adjust(char *s)
 {
 	struct word *last = words;
+	struct word *cur;
 	int w = 0;
 	int lendiff;
 	int i;
@@ -61,8 +66,13 @@
 	}
 	if (last > words)
 		last--;
-	memcpy(s, buf, last->end);
-	s[last->end] = '\0';
+	for (cur = words; cur <= last; cur++) {
+		if (cur > words)
+			s += sprintf(s, "\\h'%du'", cur->blanks);
+		memcpy(s, buf + cur->beg, cur->end - cur->beg);
+		s += cur->end - cur->beg;
+	}
+	*s = '\0';
 	lendiff = last + 1 < words + nwords ? last[1].beg : buflen;
 	memmove(buf, buf + lendiff, buflen - lendiff);
 	buflen -= lendiff;
@@ -97,7 +107,9 @@
 
 static void ren_ps(char *s)
 {
-	n_s = tr_int(s, n_s, '\0');
+	int ps = !*s || !strcmp("0", s) ? n_s0 : tr_int(s, n_s, '\0');
+	n_s0 = n_s;
+	n_s = ps;
 }
 
 void tr_ps(int argc, char **args)
@@ -104,25 +116,21 @@
 {
 	if (argc >= 2)
 		ren_ps(args[1]);
-	buflen += sprintf(buf + buflen, "\\s(%2d", n_s);
 }
 
-static int ren_ft(char *name)
+static void ren_ft(char *s)
 {
-	int fn = dev_font(name);
-	if (fn >= 0)
+	int fn = !*s || !strcmp("P", s) ? n_f0 : dev_font(s);
+	if (fn >= 0) {
+		n_f0 = n_f;
 		n_f = fn;
-	return fn;
+	}
 }
 
 void tr_ft(int argc, char **args)
 {
-	int fn;
-	if (argc < 2)
-		return;
-	fn = ren_ft(args[1]);
-	if (fn >= 0)
-		buflen += sprintf(buf + buflen, "\\f%d", n_f);
+	if (argc > 1)
+		ren_ft(args[1]);
 }
 
 void tr_fp(int argc, char **args)
@@ -133,10 +141,14 @@
 		errmsg("troff: failed to mount %s\n", args[2]);
 }
 
-static void escarg(char *s)
+static void escarg(char *s, int cmd)
 {
 	int c;
 	c = ren_next();
+	if (cmd == 's' && (c == '-' || c == '+')) {
+		*s++ = c;
+		c = ren_next();
+	}
 	if (c == '(') {
 		*s++ = ren_next();
 		*s++ = ren_next();
@@ -154,6 +166,13 @@
 		return;
 	}
 	*s++ = c;
+	if (cmd == 's' && c >= '1' && c <= '3') {
+		c = ren_next();
+		if (isdigit(c))
+			*s++ = c;
+		else
+			ren_back(c);
+	}
 	*s = '\0';
 }
 
@@ -162,14 +181,32 @@
 	char c[LLEN];
 	char arg[LINELEN];
 	struct glyph *g;
+	int g_wid;
 	struct word *word = NULL;
-	int word_beg;
 	int blanks = 0;
+	int newline = 0;
+	int r_s = n_s;
+	int r_f = n_f;
+	int esc = 0;
 	tr_br(0, NULL);
 	while (nextchar(c) > 0) {
 		g = NULL;
-		word_beg = buflen - strlen(c);
+		if (!word && wid > n_l)
+			tr_br(0, NULL);
+		if (c[0] == ' ' || c[0] == '\n') {
+			if (word) {
+				word->end = buflen;
+				word = NULL;
+			}
+			if (c[0] == '\n')
+				newline = 1;
+			else
+				blanks += charwid(dev_spacewid(), n_s);
+			continue;
+		}
+		esc = 0;
 		if (c[0] == '\\') {
+			esc = 1;
 			nextchar(c);
 			if (c[0] == '(') {
 				int l = nextchar(c);
@@ -176,7 +213,7 @@
 				l += nextchar(c + l);
 				c[l] = '\0';
 			} else if (strchr("sf", c[0])) {
-				escarg(arg);
+				escarg(arg, c[0]);
 				if (c[0] == 'f')
 					ren_ft(arg);
 				if (c[0] == 's')
@@ -184,27 +221,34 @@
 				continue;
 			}
 		}
-		g = dev_glyph(c, n_f);
-		if (!g) {
-			blanks += charwid(dev_spacewid(), n_s);
-			word = NULL;
-			continue;
-		}
 		if (!word) {
 			word = &words[nwords++];
-			word->beg = word_beg;
+			word->beg = buflen;
 			word->wid = 0;
-			word->blanks = blanks;
+			if (newline)
+				word->blanks = charwid(dev_spacewid(), n_s);
+			else
+				word->blanks = blanks;
 			wid += blanks;
+			newline = 0;
 			blanks = 0;
 		}
-		word->end = buflen;
-		word->wid += charwid(g->wid, n_s);
-		wid += charwid(g->wid, n_s);
-		if (wid > n_l) {
-			word = NULL;
-			tr_br(0, NULL);
+		if (r_s != n_s) {
+			buflen += sprintf(buf + buflen, "\\s(%02d", n_s);
+			r_s = n_s;
 		}
+		if (r_f != n_f) {
+			buflen += sprintf(buf + buflen, "\\f(%02d", n_f);
+			r_f = n_f;
+		}
+		if (utf8len(c[0]) == strlen(c))
+			buflen += sprintf(buf + buflen, "%s%s", esc ? "\\" : "", c);
+		else
+			buflen += sprintf(buf + buflen, "\\(%s", c);
+		g = dev_glyph(c, n_f);
+		g_wid = charwid(g ? g->wid : dev_spacewid(), n_s);
+		word->wid += g_wid;
+		wid += g_wid;
 	}
 	tr_br(0, NULL);
 }
--- a/xroff.c
+++ b/xroff.c
@@ -11,6 +11,8 @@
 	n_i = 0;
 	n_s = 10;
 	n_v = 12 * SC_PT;
+	n_s0 = n_s;
+	n_f0 = n_f;
 }
 
 static void compile(void)
--- a/xroff.h
+++ b/xroff.h
@@ -23,6 +23,8 @@
 #define n_l		nreg[N_ID('.', 'l')]
 #define n_v		nreg[N_ID('.', 'v')]
 #define n_i		nreg[N_ID('.', 'i')]
+#define n_f0		nreg[N_ID('\0', 'f')]	/* last font */
+#define n_s0		nreg[N_ID('\0', 's')]	/* last size */
 
 /* device related variables */
 extern int dev_res;