shithub: neatroff

Download patch

ref: eb1316e07a07693ae0f2fad1298be40b9e86052b
parent: 0ab9d55cd241a2d311b265c841031156278cb930
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu Apr 18 17:03:11 EDT 2013

out: add \X

Also makes the output cleaner by adding newlines for some
of the output commands.

--- a/dev.c
+++ b/dev.c
@@ -25,9 +25,9 @@
 
 static void dev_prologue(void)
 {
-	OUT("x T utf\n");
-	OUT("x res %d %d %d\n", dev_res, dev_hor, dev_ver);
-	OUT("x init\n");
+	out("x T utf\n");
+	out("x res %d %d %d\n", dev_res, dev_hor, dev_ver);
+	out("x init\n");
 }
 
 int dev_mnt(int pos, char *id, char *name)
@@ -43,7 +43,7 @@
 	if (fn_name[pos] != name)	/* ignore if fn_name[pos] is passed */
 		strcpy(fn_name[pos], id);
 	fn_font[pos] = fn;
-	OUT("x font %d %s\n", pos, name);
+	out("x font %d %s\n", pos, name);
 	return pos;
 }
 
@@ -104,8 +104,8 @@
 
 static void dev_epilogue(void)
 {
-	OUT("x trailer\n");
-	OUT("x stop\n");
+	out("x trailer\n");
+	out("x stop\n");
 }
 
 void dev_close(void)
--- a/out.c
+++ b/out.c
@@ -1,9 +1,39 @@
 #include <ctype.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "xroff.h"
 
+static int out_nl = 1;
+
+/* output troff code; newlines may appear only at the end of s */
+static void out_out(char *s, va_list ap)
+{
+	out_nl = strchr(s, '\n') != NULL;
+	vfprintf(stdout, s, ap);
+}
+
+/* output troff code; no preceding newline is necessary */
+static void outnn(char *s, ...)
+{
+	va_list ap;
+	va_start(ap, s);
+	out_out(s, ap);
+	va_end(ap);
+}
+
+/* output troff cmd; should appear after a newline */
+void out(char *s, ...)
+{
+	va_list ap;
+	if (!out_nl)
+		outnn("\n");
+	va_start(ap, s);
+	out_out(s, ap);
+	va_end(ap);
+}
+
 int utf8len(int c)
 {
 	if (c <= 0x7f)
@@ -38,7 +68,7 @@
 {
 	if (o_s != n) {
 		o_s = n;
-		OUT("s%d\n", o_s);
+		out("s%d\n", o_s);
 	}
 }
 
@@ -46,7 +76,7 @@
 {
 	if (n >= 0 && o_f != n) {
 		o_f = n;
-		OUT("f%d\n", o_f);
+		out("f%d\n", o_f);
 	}
 }
 
@@ -98,7 +128,7 @@
 	if (*cc)
 		*cc += sprintf(*cc, " %du", *d);
 	else
-		OUT(" %d", *d);
+		outnn(" %d", *d);
 	return s;
 }
 
@@ -111,13 +141,13 @@
 	if (cc)
 		*cc++ = c;
 	else
-		OUT("D%c", c);
+		out("D%c", c);
 	switch (c) {
 	case 'l':
 		s = tok_num(&h1, s, &cc, 'm');
 		s = tok_num(&v1, s, &cc, 'v');
 		if (!cc)			/* dpost requires this */
-			OUT(" .");
+			outnn(" .");
 		hd = h1;
 		vd = v1;
 		break;
@@ -156,11 +186,11 @@
 	if (cc)
 		*cc = '\0';
 	else
-		OUT("\n");
+		outnn("\n");
 	return hd;
 }
 
-void output(char *s)
+void out_line(char *s)
 {
 	struct glyph *g;
 	char c[GNLEN * 2];
@@ -172,7 +202,7 @@
 			if (c[0] == '(') {
 				s = utf8get(c, s);
 				s = utf8get(c + strlen(c), s);
-			} else if (strchr("Dfhsv", c[0])) {
+			} else if (strchr("DfhsvX", c[0])) {
 				s = escarg(s, arg, c[0]);
 				if (c[0] == 'D') {
 					out_draw(arg, NULL);
@@ -183,7 +213,7 @@
 					continue;
 				}
 				if (c[0] == 'h') {
-					OUT("h%d", eval(arg, 0, 'm'));
+					outnn("h%d", eval(arg, 0, 'm'));
 					continue;
 				}
 				if (c[0] == 's') {
@@ -191,19 +221,23 @@
 					continue;
 				}
 				if (c[0] == 'v') {
-					OUT("v%d", eval(arg, 0, 'v'));
+					outnn("v%d", eval(arg, 0, 'v'));
 					continue;
 				}
+				if (c[0] == 'X') {
+					out("x X %s\n", arg);
+					continue;
+				}
 			}
 		}
 		g = dev_glyph(c, o_f);
 		if (g) {
 			if (utf8len(c[0]) == strlen(c)) {
-				OUT("c%s%s", c, c[1] ? "\n" : "");
+				outnn("c%s%s", c, c[1] ? "\n" : "");
 			} else {
-				OUT("C%s\n", c);
+				out("C%s\n", c);
 			}
 		}
-		OUT("h%d", charwid(g ? g->wid : dev_spacewid(), o_s));
+		outnn("h%d", charwid(g ? g->wid : dev_spacewid(), o_s));
 	}
 }
--- a/ren.c
+++ b/ren.c
@@ -123,8 +123,8 @@
 	n_h = 0;
 	n_pg = pg;
 	bp_next = n_pg + 1;
-	OUT("p%d\n", pg);
-	OUT("V%d\n", 0);
+	out("p%d\n", pg);
+	out("V%d\n", 0);
 }
 
 static void ren_first(void)
@@ -205,7 +205,8 @@
 	}
 }
 
-static void out_line(char *out, int w, int ll, int li, int lt)
+/* flush the given line and send it to out.c */
+static void ren_line(char *s, int w, int ll, int li, int lt)
 {
 	int ljust = 0;
 	char cmd[32];
@@ -220,23 +221,23 @@
 			sprintf(cmd, "\\h'%du'", ljust);
 			sbuf_append(&cdiv->sbuf, cmd);
 		}
-		sbuf_append(&cdiv->sbuf, out);
+		sbuf_append(&cdiv->sbuf, s);
 	} else {
-		OUT("H%d\n", n_o + li + lt + ljust);
-		OUT("V%d\n", n_d);
-		output(out);
+		out("H%d\n", n_o + li + lt + ljust);
+		out("V%d\n", n_d);
+		out_line(s);
 	}
 }
 
 static void ren_br(int force)
 {
-	char out[LNLEN];
+	char buf[LNLEN];
 	int ll, li, lt, els_neg, els_pos;
 	int adj_b, w, prev_d;
 	ren_first();
 	if (!adj_empty(cadj, n_u)) {
 		adj_b = n_u && !n_na && n_j == AD_B;
-		w = adj_fill(cadj, !force && adj_b, !force && n_u, out,
+		w = adj_fill(cadj, !force && adj_b, !force && n_u, buf,
 				&ll, &li, &lt, &els_neg, &els_pos);
 		prev_d = n_d;
 		if (els_neg)
@@ -243,7 +244,7 @@
 			ren_sp(-els_neg);
 		if (!n_ns || w || els_neg || els_pos) {
 			ren_sp(0);
-			out_line(out, w, ll, li, lt);
+			ren_line(buf, w, ll, li, lt);
 			n_ns = 0;
 		}
 		if (els_pos)
@@ -471,7 +472,7 @@
 			int l = nextchar(c);
 			l += nextchar(c + l);
 			c[l] = '\0';
-		} else if (strchr("Dfhksvwx", c[0])) {
+		} else if (strchr("DfhksvwXx", c[0])) {
 			if (c[0] == 'w') {
 				render_wid();
 				return 0;
@@ -493,6 +494,8 @@
 				ren_ps(arg);
 			if (c[0] == 'v')
 				adj_put(adj, 0, "\\v'%du'", eval(arg, 0, 'v'));
+			if (c[0] == 'X')
+				adj_put(adj, 0, "\\X'%s'", arg);
 			if (c[0] == 'x')
 				adj_els(adj, eval(arg, 0, 'v'));
 			return 0;
--- a/xroff.c
+++ b/xroff.c
@@ -18,10 +18,10 @@
 
 static void compile(void)
 {
-	OUT("s%d\n", n_s);
-	OUT("f%d\n", n_f);
+	out("s%d\n", n_s);
+	out("f%d\n", n_f);
 	render();
-	OUT("V%d\n", n_p);
+	out("V%d\n", n_p);
 }
 
 void errmsg(char *fmt, ...)
--- a/xroff.h
+++ b/xroff.h
@@ -75,9 +75,6 @@
 	int n;				/* number of characters in charset */
 };
 
-/* troff output function */
-#define OUT	printf
-
 /* output device functions */
 int dev_open(char *path);
 void dev_close(void);
@@ -111,8 +108,9 @@
 
 /* rendering */
 void render(void);	/* read from in.c and print the output */
-void output(char *s);	/* output the given rendered line */
+void out_line(char *s);	/* output the given rendered line */
 int out_draw(char *s, char *cc);
+void out(char *s, ...);	/* output troff cmd */
 
 /* troff commands */
 void tr_bp(char **args);