shithub: neatroff

Download patch

ref: 7127cb9afb7ff6e609b6b9b3cecf3705bdeb5cf7
parent: 96f08d8dc0198c6c1ac478349ed76398c5cf7401
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Nov 17 17:23:45 EST 2012

filling output lines

--- a/dev.c
+++ b/dev.c
@@ -126,9 +126,9 @@
 
 /* glyph handling functions */
 
-struct glyph *dev_glyph(char *c)
+struct glyph *dev_glyph(char *c, int fn)
 {
-	struct glyph *g = font_find(fn_font[n_f], c);
+	struct glyph *g = font_find(fn_font[fn], c);
 	int i;
 	if (g)
 		return g;
@@ -139,9 +139,9 @@
 	return NULL;
 }
 
-struct glyph *dev_glyph_byid(char *id)
+struct glyph *dev_glyph_byid(char *id, int fn)
 {
-	return font_glyph(fn_font[n_f], id);
+	return font_glyph(fn_font[fn], id);
 }
 
 struct glyph *dev_ligature(char **s, int n)
--- a/out.c
+++ b/out.c
@@ -1,10 +1,24 @@
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "xroff.h"
 
-static int out_blank = 0;
+#define LINELEN		1024
 
+struct word {
+	int beg;	/* word beginning offset in buf */
+	int end;	/* word ending offset in buf */
+	int wid;	/* word width */
+	int blanks;	/* blanks before word */
+};
+
+static char buf[LINELEN];		/* output buffer */
+static int buflen;
+static struct word words[LINELEN];	/* words in the buffer */
+static int nwords;
+static int wid;				/* total width of the buffer */
+
 static int utf8len(int c)
 {
 	if (c <= 0x7f)
@@ -33,34 +47,156 @@
 	for (i = 1; i < l; i++)
 		s[i] = tr_next();
 	s[l] = '\0';
+	memcpy(buf + buflen, s, l + 1);
+	buflen += l;
 	return l;
 }
 
-static void out_sp(int n)
+static char *utf8get(char *d, char *s)
 {
+	int l = utf8len(*s);
+	int i;
+	for (i = 0; i < l; i++)
+		d[i] = s[i];
+	d[l] = '\0';
+	return s + l;
+}
+
+static char *readint(char *s, int *d)
+{
+	*d = 0;
+	while (isdigit(*s))
+		*d = *d * 10 + *s++ - '0';
+	return s;
+}
+
+static int o_s, o_f;
+
+static void flush(char *s)
+{
+	struct glyph *g;
+	char c[LLEN];
+	int o_blank = 0;
 	printf("H%d", n_o + n_i);
-	printf("v%d\n", n_v * (n + 1));
-	out_blank = 0;
+	while (*s) {
+		s = utf8get(c, s);
+		if (c[0] == '\\') {
+			s = utf8get(c, s);
+			if (c[0] == 's') {
+				s = readint(s, &o_s);
+				printf("s%d\n", o_s);
+				continue;
+			}
+			if (c[0] == 'f') {
+				s = readint(s, &o_f);
+				printf("f%d\n", o_f);
+				continue;
+			}
+			if (c[0] == '(') {
+				s = utf8get(c, s);
+				s = utf8get(c + strlen(c), s);
+			}
+		}
+		g = dev_glyph(c, o_f);
+		if (g) {
+			if (o_blank)
+				printf("h%d", dev_spacewid() * o_s / dev_uwid);
+			if (utf8len(c[0]) == strlen(c)) {
+				printf("c%s%s", c, c[1] ? "\n" : "");
+			} else {
+				printf("C%s\n", c);
+			}
+			printf("h%d", g->wid * o_s / dev_uwid);
+			o_blank = 0;
+		} else {
+			o_blank = 1;
+		}
+	}
 }
 
+static void down(int n)
+{
+	printf("v%d\n", n);
+}
+
+static void adjust(char *s)
+{
+	struct word *last = words;
+	int w = 0;
+	int lendiff;
+	int i;
+	while (last < words + nwords && w + last->wid + last->blanks <= n_l) {
+		w += last->wid + last->blanks;
+		last++;
+	}
+	if (last > words)
+		last--;
+	memcpy(s, buf, last->end);
+	s[last->end] = '\0';
+	lendiff = last + 1 < words + nwords ? last[1].beg : buflen;
+	memmove(buf, buf + lendiff, buflen - lendiff);
+	buflen -= lendiff;
+	nwords -= last - words + 1;
+	memmove(words, last + 1, nwords * sizeof(words[0]));
+	wid -= w;
+	for (i = 0; i < nwords; i++) {
+		words[i].beg -= lendiff;
+		words[i].end -= lendiff;
+	}
+	if (nwords)
+		wid -= words[0].blanks;
+	words[0].blanks = 0;
+}
+
 void tr_br(int argc, char **args)
 {
-	out_sp(0);
+	char out[LINELEN];
+	buf[buflen] = '\0';
+	if (buflen) {
+		adjust(out);
+		flush(out);
+		down(n_v);
+	}
+	o_s = n_s;
+	o_f = n_f;
 }
 
 void tr_sp(int argc, char **args)
 {
-	out_sp(argc > 1 ? atoi(args[1]) : 1);
+	tr_br(0, NULL);
+	if (argc > 1)
+		down(n_v * atoi(args[1]));
 }
 
+void tr_ps(int argc, char **args)
+{
+	if (argc >= 2)
+		n_s = atoi(args[1]);
+	buflen += sprintf(buf + buflen, "\\s%d", n_s);
+}
+
+void tr_ft(int argc, char **args)
+{
+	int fn;
+	if (argc < 2)
+		return;
+	fn = dev_font(args[1]);
+	if (fn >= 0)
+		n_f = fn;
+	buflen += sprintf(buf + buflen, "\\f%d", n_f);
+}
+
 void render(void)
 {
 	char c[LLEN];
 	struct glyph *g;
-	int fp = n_f;
-	int ps = n_s;
+	struct word *word = NULL;
+	int word_beg;
+	int blanks = 0;
+	tr_br(0, NULL);
 	while (nextchar(c) > 0) {
 		g = NULL;
+		word_beg = buflen - strlen(c);
 		if (c[0] == '\\') {
 			nextchar(c);
 			if (c[0] == '(') {
@@ -69,27 +205,24 @@
 				c[l] = '\0';
 			}
 		}
-		g = dev_glyph(c);
-		if (ps != n_s) {
-			printf("s%d\n", n_s);
-			ps = n_s;
+		g = dev_glyph(c, n_f);
+		if (!g) {
+			blanks = dev_spacewid() * n_s / dev_uwid;
+			word = NULL;
+			continue;
 		}
-		if (fp != n_f) {
-			printf("f%d\n", n_f);
-			fp = n_f;
+		if (!word) {
+			word = &words[nwords++];
+			word->beg = word_beg;
+			word->wid = 0;
+			word->blanks = blanks;
+			wid += blanks;
 		}
-		if (g) {
-			if (out_blank)
-				printf("h%d", dev_spacewid() * n_s / dev_uwid);
-			if (utf8len(c[0]) == strlen(c)) {
-				printf("c%s%s", c, c[1] ? "\n" : "");
-			} else {
-				printf("C%s\n", c);
-			}
-			printf("h%d", g->wid * n_s / dev_uwid);
-			out_blank = 0;
-		} else {
-			out_blank = 1;
-		}
+		word->end = buflen;
+		word->wid += g->wid * n_s / dev_uwid;
+		wid += g->wid * n_s / dev_uwid;
+		if (wid > n_l)
+			tr_br(0, NULL);
 	}
+	tr_br(0, NULL);
 }
--- a/tr.c
+++ b/tr.c
@@ -10,20 +10,10 @@
 
 static int tr_nl = 1;
 
-static void tr_ft(int argc, char **args)
+static void tr_ll(int argc, char **args)
 {
-	int fn;
-	if (argc < 2)
-		return;
-	fn = dev_font(args[1]);
-	if (fn >= 0)
-		n_f = fn;
-}
-
-static void tr_ps(int argc, char **args)
-{
 	if (argc >= 2)
-		n_s = atoi(args[1]);
+		n_l = atoi(args[1]) * SC_PT;
 }
 
 static void tr_vs(int argc, char **args)
@@ -32,16 +22,10 @@
 		n_v = atoi(args[1]) * SC_PT;
 }
 
-static void tr_ll(int argc, char **args)
-{
-	if (argc >= 2)
-		n_v = atoi(args[1]) * SC_PT;
-}
-
 static void tr_in(int argc, char **args)
 {
 	if (argc >= 2)
-		n_v = atoi(args[1]) * SC_PT;
+		n_i = atoi(args[1]) * SC_PT;
 }
 
 static void tr_readcmd(char *s)
@@ -92,8 +76,8 @@
 	{"ps", tr_ps},
 	{"sp", tr_sp},
 	{"vs", tr_vs},
-	{"vs", tr_ll},
-	{"vs", tr_in},
+	{"ll", tr_ll},
+	{"in", tr_in},
 };
 
 int tr_next(void)
--- a/xroff.h
+++ b/xroff.h
@@ -59,8 +59,8 @@
 struct glyph *font_find(struct font *fn, char *name);
 
 /* glyph handling functions */
-struct glyph *dev_glyph(char *c);
-struct glyph *dev_glyph_byid(char *id);
+struct glyph *dev_glyph(char *c, int fn);
+struct glyph *dev_glyph_byid(char *id, int fn);
 int dev_spacewid(void);
 
 /* different layers of neatroff */
@@ -79,3 +79,5 @@
 void tr_br(int argc, char **args);
 void tr_sp(int argc, char **args);
 void tr_nr(int argc, char **args);
+void tr_ps(int argc, char **args);
+void tr_ft(int argc, char **args);