shithub: neatroff

Download patch

ref: efde0d26267c0cc73323abd95d5fa5357383ecf1
parent: 6b44fd3626537191cc393a23bda5b7c091b8697b
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu Jul 25 11:00:01 EDT 2013

ren: add .nm and .nn

--- a/reg.c
+++ b/reg.c
@@ -23,31 +23,15 @@
 static struct env *envs[NREGS2];/* environments */
 static struct env *env;		/* current enviroment */
 static int env_id;		/* current environment id */
-static int eregs_idx[NREGS];	/* register environment index in eregs[] */
+static int eregs_idx[NREGS2];	/* register environment index in eregs[] */
 
-static int eregs[] = {		/* environment-specific number registers */
-	REG('.', 'f'),
-	REG('.', 'i'),
-	REG('.', 'j'),
-	REG('.', 'l'),
-	REG('.', 'L'),
-	REG('.', 'm'),
-	REG('.', 's'),
-	REG('.', 'u'),
-	REG('.', 'v'),
-	REG(0, 'c'),
-	REG(0, 'f'),
-	REG(0, 'h'),
-	REG(0, 'i'),
-	REG(0, 'l'),
-	REG(0, 'L'),
-	REG(0, 'n'),
-	REG(0, 'm'),
-	REG(0, 'p'),
-	REG(0, 's'),
-	REG(0, 't'),
-	REG(0, 'T'),
-	REG(0, 'v'),
+static char *eregs[] = {	/* environment-specific number registers */
+	"ln", ".f", ".i", ".j", ".l",
+	".L", ".nI", ".nm", ".nM", ".nn",
+	".nS", ".m", ".s", ".u", ".v",
+	"\0c", "\0f", "\0h", "\0i", "\0l",
+	"\0L", "\0n", "\0m", "\0p", "\0s",
+	"\0t", "\0T", "\0v",
 };
 
 /* return the address of a number register */
@@ -200,6 +184,8 @@
 		n_lt = SC_IN * 65 / 10;
 		n_hy = 1;
 		n_ss = 12;
+		n_nM = 1;
+		n_nS = 1;
 		strcpy(env->hc, "\\%");
 		adj_ll(env->adj, n_l);
 		adj_in(env->adj, n_i);
@@ -223,7 +209,7 @@
 	int i;
 	init_time();
 	for (i = 0; i < LEN(eregs); i++)
-		eregs_idx[eregs[i]] = i + 1;
+		eregs_idx[map(eregs[i])] = i + 1;
 	env_set(0);
 }
 
--- a/ren.c
+++ b/ren.c
@@ -220,8 +220,8 @@
 	}
 }
 
-/* flush the given line and send it to out.c */
-static void ren_line(char *s, int w, int ad, int ll, int li, int lt)
+/* line adjustment */
+static void ren_ljust(struct sbuf *spre, int w, int ad, int ll, int li, int lt)
 {
 	int ljust = lt >= 0 ? lt : li;
 	int llen = ll - ljust;
@@ -230,16 +230,25 @@
 		ljust += llen > w ? (llen - w) / 2 : 0;
 	if (ad == AD_R)
 		ljust += llen - w;
+	if (ljust)
+		sbuf_printf(spre, "%ch'%du'", c_ec, ljust);
+	if (cdiv && cdiv->dl < w)
+		cdiv->dl = w;
+}
+
+/* append the line to the current diversion or send it to out.c */
+static void ren_line(struct sbuf *spre, struct sbuf *sbuf)
+{
 	if (cdiv) {
-		if (cdiv->dl < w)
-			cdiv->dl = w;
-		if (ljust)
-			sbuf_printf(&cdiv->sbuf, "%ch'%du'", c_ec, ljust);
-		sbuf_append(&cdiv->sbuf, s);
+		if (!sbuf_empty(spre))
+			sbuf_append(&cdiv->sbuf, sbuf_buf(spre));
+		sbuf_append(&cdiv->sbuf, sbuf_buf(sbuf));
 	} else {
-		out("H%d\n", n_o + ljust);
+		out("H%d\n", n_o);
 		out("V%d\n", n_d);
-		out_line(s);
+		if (!sbuf_empty(spre))
+			out_line(sbuf_buf(spre));
+		out_line(sbuf_buf(sbuf));
 	}
 }
 
@@ -251,16 +260,49 @@
 		out("%s\n", s);
 }
 
+static int zwid(void)
+{
+	struct glyph *g = dev_glyph("0", n_f);
+	return charwid(n_f, n_s, g ? g->wid : SC_DW);
+}
+
+/* append the line number to the output line */
+static void ren_lnum(struct sbuf *spre)
+{
+	char num[16] = "";
+	char dig[16] = "";
+	struct wb wb;
+	int i = 0;
+	wb_init(&wb);
+	if (n_nn <= 0 && (n_ln % n_nM) == 0)
+		sprintf(num, "%d", n_ln);
+	wb_hmov(&wb, n_nI * zwid());
+	if (strlen(num) < 3)
+		wb_hmov(&wb, (3 - strlen(num)) * zwid());
+	while (num[i]) {
+		dig[0] = num[i++];
+		wb_put(&wb, dig);
+	}
+	wb_hmov(&wb, n_nS * zwid());
+	sbuf_append(spre, sbuf_buf(&wb.sbuf));
+	wb_done(&wb);
+	if (n_nn > 0)
+		n_nn--;
+	else
+		n_ln++;
+}
+
 /* return 1 if triggered a trap */
-static int ren_bradj(struct adj *adj, int fill, int ad)
+static int ren_bradj(struct adj *adj, int fill, int ad, int body)
 {
 	char cmd[16];
-	struct sbuf sbuf;
+	struct sbuf sbuf, spre;
 	int ll, li, lt, els_neg, els_pos;
 	int w, prev_d, lspc;
 	ren_first();
 	if (!adj_empty(adj, fill)) {
 		sbuf_init(&sbuf);
+		sbuf_init(&spre);
 		w = adj_fill(adj, ad == AD_B, fill, n_hy, &sbuf,
 				&ll, &li, &lt, &els_neg, &els_pos);
 		prev_d = n_d;
@@ -268,9 +310,13 @@
 			ren_sp(-els_neg, 1);
 		if (!n_ns || !sbuf_empty(&sbuf) || els_neg || els_pos) {
 			ren_sp(0, 0);
-			ren_line(sbuf_buf(&sbuf), w, ad, ll, li, lt);
+			if (!sbuf_empty(&sbuf) && n_nm && body)
+				ren_lnum(&spre);
+			ren_ljust(&spre, w, ad, ll, li, lt);
+			ren_line(&spre, &sbuf);
 			n_ns = 0;
 		}
+		sbuf_done(&spre);
 		sbuf_done(&sbuf);
 		if (els_pos)
 			ren_sp(els_pos, 1);
@@ -293,8 +339,12 @@
 /* return 1 if triggered a trap */
 static int ren_br(int force)
 {
-	return ren_bradj(cadj, !force && !n_ce && n_u,
-			n_ce ? AD_C : (n_u && !n_na && (n_j != AD_B || !force) ? n_j : AD_L));
+	int ad = n_j;
+	if (!n_u || n_na || (n_j == AD_B && force))
+		ad = AD_L;
+	if (n_ce)
+		ad = AD_C;
+	return ren_bradj(cadj, !force && !n_ce && n_u, ad, 1);
 }
 
 void tr_br(char **args)
@@ -575,7 +625,6 @@
 
 static void ren_cmd(struct wb *wb, int c, char *arg)
 {
-	struct glyph *g;
 	switch (c) {
 	case ' ':
 		wb_hmov(wb, spacewid(n_f, n_s));
@@ -636,8 +685,7 @@
 		wb_els(wb, eval(arg, 'v'));
 		break;
 	case '0':
-		g = dev_glyph("0", n_f);
-		wb_hmov(wb, charwid(n_f, n_s, g ? g->wid : SC_DW));
+		wb_hmov(wb, zwid());
 		break;
 	case '|':
 		wb_hmov(wb, SC_EM / 6);
@@ -802,7 +850,7 @@
 	adj_ll(adj, n_lt);
 	adj_wb(adj, &wb);
 	adj_nl(adj);
-	ren_bradj(adj, 0, AD_L);
+	ren_bradj(adj, 0, AD_L, 0);
 	adj_free(adj);
 	wb_done(&wb2);
 	wb_done(&wb);
--- a/roff.h
+++ b/roff.h
@@ -253,7 +253,6 @@
 void ren_bracket(struct wb *wb, char *arg);	/* \b */
 void ren_over(struct wb *wb, char *arg);	/* \o */
 void ren_draw(struct wb *wb, char *arg);	/* \D */
-void ren_putc(struct wb *wb, char *c);		/* handling .cs and .bd */
 
 /* out.c */
 void out_line(char *s);				/* output rendered line */
@@ -337,6 +336,11 @@
 #define n_l		(*nreg(REG('.', 'l')))
 #define n_L		(*nreg(REG('.', 'L')))
 #define n_n		(*nreg(REG('.', 'n')))
+#define n_nI		(*nreg(map(".nI")))	/* i for .nm */
+#define n_nm		(*nreg(map(".nm")))	/* .nm enabled */
+#define n_nM		(*nreg(map(".nM")))	/* m for .nm */
+#define n_nn		(*nreg(map(".nn")))	/* remaining .nn */
+#define n_nS		(*nreg(map(".nS")))	/* s for .nm */
 #define n_m		(*nreg(REG('.', 'm')))
 #define n_o		(*nreg(REG('.', 'o')))
 #define n_p		(*nreg(REG('.', 'p')))
@@ -346,6 +350,7 @@
 #define n_ct		(*nreg(REG('c', 't')))
 #define n_dl		(*nreg(REG('d', 'l')))
 #define n_dn		(*nreg(REG('d', 'n')))
+#define n_ln		(*nreg(REG('l', 'n')))
 #define n_nl		(*nreg(REG('n', 'l')))
 #define n_sb		(*nreg(REG('s', 'b')))
 #define n_st		(*nreg(REG('s', 't')))
--- a/tr.c
+++ b/tr.c
@@ -452,6 +452,28 @@
 	dev_setcs(dev_pos(args[1]), args[2] ? eval(args[2], 0) : 0);
 }
 
+static void tr_nm(char **args)
+{
+	if (!args[1]) {
+		n_nm = 0;
+		return;
+	}
+	n_nm = 1;
+	n_ln = eval_re(args[1], n_ln, 0);
+	n_ln = MAX(0, n_ln);
+	if (args[2] && isdigit(args[2][0]))
+		n_nM = MAX(1, eval(args[2], 0));
+	if (args[3] && isdigit(args[3][0]))
+		n_nS = MAX(0, eval(args[3], 0));
+	if (args[4] && isdigit(args[4][0]))
+		n_nI = MAX(0, eval(args[4], 0));
+}
+
+static void tr_nn(char **args)
+{
+	n_nn = args[1] ? eval(args[1], 0) : 1;
+}
+
 static void tr_bd(char **args)
 {
 	if (!args[1] || !strcmp("S", args[1]))
@@ -675,6 +697,8 @@
 	{"ne", tr_ne},
 	{"nf", tr_nf},
 	{"nh", tr_nh},
+	{"nm", tr_nm},
+	{"nn", tr_nn},
 	{"nr", tr_nr, mkargs_reg1},
 	{"ns", tr_ns},
 	{"nx", tr_nx},