ref: 5a590125a2830e7106fa78dacb0e1a9991f8a4cb
parent: 3b1dedaa9cfe9e5b78166054f829e4c36bb8e56e
author: Ali Gholami Rudi <ali@rudi.ir>
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;