shithub: neatroff

Download patch

ref: ec160f1296fa62bf0e739cd2d670854261bfafd2
parent: 9b90808b2c90134f7d96534908feea5a7769051c
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat May 25 17:34:06 EDT 2013

ren: add .em

--- a/in.c
+++ b/in.c
@@ -20,7 +20,7 @@
 static char files[NFILES][PATHLEN];
 static int nfiles;
 static int cfile;
-static int in_last[2];		/* the last chars returned from in_next() */
+static int in_last[2] = {'\n'};	/* the last chars returned from in_next() */
 
 static char **args_init(char **args);
 static void args_free(char **args);
@@ -119,13 +119,18 @@
 
 int in_next(void)
 {
-	in_last[1] = in_last[0];
-	in_last[0] = in_read();
-	return in_last[0];
+	int c = in_read();
+	if (c >= 0) {
+		in_last[1] = in_last[0];
+		in_last[0] = c;
+	}
+	return c;
 }
 
 void in_back(int c)
 {
+	if (c < 0)
+		return;
 	in_last[0] = in_last[1];
 	if (buf)
 		buf->unbuf[buf->un++] = c;
--- a/ren.c
+++ b/ren.c
@@ -21,6 +21,7 @@
 static struct div divs[NPREV];	/* diversion stack */
 static struct div *cdiv;	/* current diversion */
 static int ren_div;		/* rendering a diversion */
+static int trap_em = -1;	/* end macro */
 
 static struct wb ren_wb;	/* the main ren.c word buffer */
 static int ren_nl;		/* just after newline */
@@ -30,7 +31,9 @@
 
 static int bp_first = 1;	/* prior to the first page */
 static int bp_next = 1;		/* next page number */
-static int bp_force;		/* execute the traps until the next page */
+static int bp_count;		/* number of pages so far */
+static int bp_ejected;		/* current ejected page */
+static int bp_final;		/* 1: the final page, 2: the 2nd final page */
 
 static int c_fa;		/* field delimiter */
 static char c_fb[GNLEN];	/* field padding */
@@ -55,7 +58,7 @@
 		cdiv->treg = -1;
 		if (args[0][2] == 'a' && str_get(cdiv->reg))	/* .da */
 			sbuf_append(&cdiv->sbuf, str_get(cdiv->reg));
-		sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, DIV_BEG);
+		sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, TR_DIVBEG);
 		cdiv->prev_d = n_d;
 		cdiv->prev_h = n_h;
 		cdiv->prev_mk = n_mk;
@@ -66,7 +69,7 @@
 		n_ns = 0;
 	} else if (cdiv) {
 		sbuf_putnl(&cdiv->sbuf);
-		sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, DIV_END);
+		sbuf_printf(&cdiv->sbuf, "%c%s\n", c_cc, TR_DIVEND);
 		str_set(cdiv->reg, sbuf_buf(&cdiv->sbuf));
 		sbuf_done(&cdiv->sbuf);
 		n_dl = cdiv->dl;
@@ -105,13 +108,16 @@
 static int trap_pos(int pos);
 static void trap_exec(int reg);
 
-static void ren_page(int pg)
+static void ren_page(int pg, int force)
 {
+	if (!force && bp_final)
+		return;
 	n_nl = 0;
 	n_d = 0;
 	n_h = 0;
 	n_pg = pg;
 	bp_next = n_pg + 1;
+	bp_count++;
 	out("p%d\n", pg);
 	out("V%d\n", 0);
 	if (trap_pos(-1) == 0)
@@ -122,7 +128,7 @@
 {
 	if (bp_first && !cdiv) {
 		bp_first = 0;
-		ren_page(bp_next);
+		ren_page(bp_next, 1);
 	}
 }
 
@@ -144,17 +150,8 @@
 	}
 }
 
-static void push_ne(void)
-{
-	char buf[32];
-	sprintf(buf, "%cne %du\n", c_cc, n_p);
-	in_pushnl(buf, NULL);
-}
-
 static void trap_exec(int reg)
 {
-	if (bp_force)
-		push_ne();
 	if (str_get(reg))
 		in_pushnl(str_get(reg), NULL);
 }
@@ -187,8 +184,7 @@
 static int ren_pagelimit(int ne)
 {
 	if (detect_pagelimit(ne)) {
-		bp_force = 0;
-		ren_page(bp_next);
+		ren_page(bp_next, 0);
 		return 1;
 	}
 	return 0;
@@ -344,15 +340,45 @@
 		ren_pagelimit(n);
 }
 
-void tr_bp(char **args)
+static void push_eject(void)
 {
+	char buf[32];
+	bp_ejected = bp_count;
+	sprintf(buf, "%c%s %d\n", c_cc, TR_EJECT, bp_ejected);
+	in_pushnl(buf, NULL);
+}
+
+static void push_br(void)
+{
 	char br[8] = {c_cc, 'b', 'r', '\n'};
+	in_pushnl(br, NULL);
+}
+
+static void ren_eject(int id)
+{
+	if (id == bp_ejected && !cdiv) {
+		if (detect_traps(n_d, n_p)) {
+			push_eject();
+			ren_traps(n_d, n_p, 1);
+		} else {
+			bp_ejected = 0;
+			ren_page(bp_next, 0);
+		}
+	}
+}
+
+void tr_eject(char **args)
+{
+	ren_eject(atoi(args[1]));
+}
+
+void tr_bp(char **args)
+{
 	if (!cdiv && (args[1] || !n_ns)) {
-		if (!bp_force)
-			push_ne();
+		if (bp_ejected != bp_count)
+			push_eject();
 		if (args[0][0] == c_cc)
-			in_pushnl(br, NULL);
-		bp_force = 1;
+			push_br();
 		if (args[1])
 			bp_next = eval_re(args[1], n_pg, 0);
 	}
@@ -751,7 +777,18 @@
 	tr_first();
 	ren_first();			/* transition to the first page */
 	c = ren_next();
-	while (c >= 0) {
+	while (1) {
+		if (c < 0) {
+			if (bp_final)
+				break;
+			bp_final = 1;
+			push_eject();
+			push_br();
+			if (trap_em >= 0)
+				trap_exec(trap_em);
+			c = ren_next();
+			continue;
+		}
 		ren_cnl = c == '\n';
 		if (c == ' ' || c == '\n') {
 			adj_swid(cadj, charwid(dev_spacewid(), n_s));
@@ -778,6 +815,9 @@
 		ren_nl = c == '\n';
 		c = ren_next();
 	}
+	bp_final = 2;
+	if (!adj_empty(cadj, 0))
+		ren_page(bp_next, 1);
 	ren_br(1);
 	wb_done(wb);
 }
@@ -865,9 +905,16 @@
 	}
 }
 
+void tr_em(char **args)
+{
+	trap_em = args[1] ? REG(args[1][0], args[1][1]) : -1;
+}
+
 static int trap_pos(int pos)
 {
 	int ret = trap_first(pos);
+	if (bp_final > 1)
+		return -1;
 	if (cdiv)
 		return cdiv->treg && cdiv->tpos > pos ? cdiv->tpos : -1;
 	return ret >= 0 ? tposval(ret) : -1;
--- a/tr.c
+++ b/tr.c
@@ -576,8 +576,9 @@
 	void (*f)(char **args);
 	int (*args)(char **args, char *buf, int len);
 } cmds[] = {
-	{DIV_BEG, tr_divbeg},
-	{DIV_END, tr_divend},
+	{TR_DIVBEG, tr_divbeg},
+	{TR_DIVEND, tr_divend},
+	{TR_EJECT, tr_eject},
 	{"ad", tr_ad},
 	{"am", tr_de, mkargs_reg1},
 	{"as", tr_as, mkargs_ds},
@@ -594,6 +595,7 @@
 	{"dt", tr_dt},
 	{"ec", tr_ec},
 	{"el", tr_el, mkargs_null},
+	{"em", tr_em},
 	{"eo", tr_eo},
 	{"ev", tr_ev},
 	{"ex", tr_ex},
@@ -649,7 +651,7 @@
 	char cmd[RLEN];
 	char buf[LNLEN];
 	struct cmd *req;
-	while (tr_nl && (c == c_cc || c == c_c2)) {
+	while (tr_nl && c >= 0 && (c == c_cc || c == c_c2)) {
 		nl = 1;
 		memset(args, 0, sizeof(args));
 		args[0] = cmd;
@@ -673,7 +675,7 @@
 		c = cp_next();
 		nl = c == '\n';
 	}
-	tr_nl = nl;
+	tr_nl = c < 0 || nl;
 	return c;
 }
 
--- a/xroff.h
+++ b/xroff.h
@@ -237,6 +237,7 @@
 void tr_divbeg(char **args);
 void tr_divend(char **args);
 void tr_dt(char **args);
+void tr_em(char **args);
 void tr_ev(char **args);
 void tr_fc(char **args);
 void tr_fi(char **args);
@@ -259,6 +260,7 @@
 void tr_ta(char **args);
 void tr_ti(char **args);
 void tr_wh(char **args);
+void tr_eject(char **args);
 
 void tr_init(void);
 
@@ -269,9 +271,10 @@
 void schar_read(char *d, int (*next)(void));
 int schar_jump(char *d, int (*next)(void), void (*back)(int));
 
-/* diversions */
-#define DIV_BEG		"&<"
-#define DIV_END		"&>"
+/* internal commands */
+#define TR_DIVBEG	"\07<"	/* diversion begins */
+#define TR_DIVEND	"\07>"	/* diversion ends */
+#define TR_EJECT	"\07P"	/* page eject */
 
 /* builtin number registers; n_X for .X register */
 #define REG(c1, c2)	((c1) * 256 + (c2))