shithub: neatroff

Download patch

ref: 5a590125a2830e7106fa78dacb0e1a9991f8a4cb
parent: 3b1dedaa9cfe9e5b78166054f829e4c36bb8e56e
author: Ali Gholami Rudi <[email protected]>
date: Sun Jun 23 14:48:52 EDT 2013

wb: store the previous wb_put() argument in wb->prev_c

--- a/roff.h
+++ b/roff.h
@@ -147,9 +147,9 @@
 
 /* variable length string buffer */
 struct sbuf {
-	char *s;
-	int sz;
-	int n;
+	char *s;		/* allocated buffer */
+	int sz;			/* buffer size */
+	int n;			/* length of the string stored in s */
 	int prev_n;		/* n before the last sbuf_append() */
 };
 
@@ -160,9 +160,9 @@
 void sbuf_append(struct sbuf *sbuf, char *s);
 void sbuf_printf(struct sbuf *sbuf, char *s, ...);
 void sbuf_putnl(struct sbuf *sbuf);
-int sbuf_empty(struct sbuf *sbuf);
-char *sbuf_last(struct sbuf *sbuf);
 void sbuf_pop(struct sbuf *sbuf);
+int sbuf_len(struct sbuf *sbuf);
+int sbuf_empty(struct sbuf *sbuf);
 
 /* word buffer */
 struct wb {
@@ -173,7 +173,9 @@
 	int els_neg, els_pos;	/* extra line spacing */
 	int h, v;		/* buffer vertical and horizontal positions */
 	int ct, sb, st;		/* \w registers */
-	int prev_h;		/* previous value of h */
+	char prev_c[GNLEN];	/* previous character added via wb_put() */
+	int prev_h;		/* wb->h after wb_put() calls */
+	int prev_l;		/* sbuf_len(&wb->sbuf) after wb_put() calls */
 };
 
 void wb_init(struct wb *wb);
--- a/sbuf.c
+++ b/sbuf.c
@@ -66,11 +66,12 @@
 	return sbuf->s;
 }
 
-char *sbuf_last(struct sbuf *sbuf)
+int sbuf_len(struct sbuf *sbuf)
 {
-	return sbuf->prev_n < sbuf->n ? sbuf_buf(sbuf) + sbuf->prev_n : NULL;
+	return sbuf->n;
 }
 
+/* undo last sbuf_append() */
 void sbuf_pop(struct sbuf *sbuf)
 {
 	if (sbuf->prev_n < sbuf->n)
--- a/wb.c
+++ b/wb.c
@@ -97,6 +97,8 @@
 			sbuf_printf(&wb->sbuf, "%cC'%s'", c_ec, c);
 	}
 	if (strcmp(c_hc, c)) {
+		strcpy(wb->prev_c, c);
+		wb->prev_l = sbuf_len(&wb->sbuf);
 		wb->prev_h = wb->h;
 		wb->h += charwid(g ? g->wid : SC_DW, R_S(wb));
 		wb->ct |= g ? g->type : 0;
@@ -107,13 +109,10 @@
 /* return zero if c formed a ligature with its previous character */
 int wb_lig(struct wb *wb, char *c)
 {
-	char *p = sbuf_last(&wb->sbuf);
-	char lig[GNLEN];
-	if (!p || strlen(p) + strlen(c) + 4 > GNLEN)
+	char lig[GNLEN * 2];
+	if (wb->prev_l != sbuf_len(&wb->sbuf) || !wb->prev_c[0])
 		return 1;
-	if (p[0] == c_ec && p[1] == '(')
-		p += 2;
-	sprintf(lig, "%s%s", p, c);
+	sprintf(lig, "%s%s", wb->prev_c, c);
 	if (font_lig(dev_font(R_F(wb)), lig)) {
 		wb->h = wb->prev_h;
 		sbuf_pop(&wb->sbuf);
@@ -126,9 +125,10 @@
 /* return 0 if pairwise kerning was done */
 int wb_kern(struct wb *wb, char *c)
 {
-	char *p = sbuf_last(&wb->sbuf);
 	int val;
-	val = p ? font_kern(dev_font(R_F(wb)), p, c) : 0;
+	if (wb->prev_l != sbuf_len(&wb->sbuf) || !wb->prev_c[0])
+		return 1;
+	val = font_kern(dev_font(R_F(wb)), wb->prev_c, c);
 	if (val)
 		wb_hmov(wb, charwid(val, R_S(wb)));
 	return !val;