ref: ebce0cd6c0ceacec630657ae14df6f6110ce0d28
parent: 8cf75f23fe223588cbd8e30f302bf77b766511bc
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu May 1 07:43:00 EDT 2014
fmt: preserve current font and size when hyphenating
--- a/fmt.c
+++ b/fmt.c
@@ -205,36 +205,51 @@
}
}
-/* copy word buffer wb in fmt->words[i] */
+static void fmt_wb2word(struct fmt *f, struct word *word, struct wb *wb,
+ int hy, int str, int gap)
+{
+ int len = strlen(wb_buf(wb));
+ word->s = malloc(len + 1);
+ memcpy(word->s, wb_buf(wb), len + 1);
+ word->wid = wb_wid(wb);
+ word->elsn = wb->els_neg;
+ word->elsp = wb->els_pos;
+ word->hy = hy ? wb_dashwid(wb) : 0;
+ word->str = str;
+ word->gap = gap;
+}
+
static void fmt_insertword(struct fmt *f, struct wb *wb, int gap)
{
int hyidx[NHYPHS];
- int hywid[NHYPHS];
- int hydash[NHYPHS];
- struct word *w;
- char *beg, *end;
+ int hyins[NHYPHS] = {0};
char *src = wb_buf(wb);
+ struct wb wbc;
+ char *beg;
+ char *end;
int n, i;
- n = wb_hyph(src, hyidx, hywid, hydash, n_hy);
+ int cf, cs, cm;
+ int hy = 0; /* insert hyphens */
+ n = wb_hyphmark(src, hyidx, hyins);
+ if (!n && n_hy && (n = wb_hyph(src, hyidx, n_hy)) > 0)
+ hy = 1;
+ if (n <= 0) {
+ fmt_wb2word(f, &f->words[f->nwords++], wb, 0, 1, gap);
+ return;
+ }
+ wb_init(&wbc);
for (i = 0; i <= n; i++) {
- w = &f->words[f->nwords++];
beg = src + (i > 0 ? hyidx[i - 1] : 0);
end = src + (i < n ? hyidx[i] : strlen(src));
- w->s = malloc(end - beg + 1);
- memcpy(w->s, beg, end - beg);
- w->s[end - beg] = '\0';
- if (n) {
- w->wid = (i < n ? hywid[i] : wb_wid(wb)) -
- (i > 0 ? hywid[i - 1] : 0);
- } else {
- w->wid = wb_wid(wb);
- }
- w->elsn = wb->els_neg;
- w->elsp = wb->els_pos;
- w->hy = i < n ? hydash[i] : 0;
- w->str = i == 0;
- w->gap = i == 0 ? gap : 0;
+ wb_catstr(&wbc, beg, end);
+ fmt_wb2word(f, &f->words[f->nwords++], &wbc,
+ i < n && (hy || hyins[i]), i == 0, i == 0 ? gap : 0);
+ /* restoring wbc */
+ wb_fnszget(&wbc, &cs, &cf, &cm);
+ wb_reset(&wbc);
+ wb_fnszset(&wbc, cs, cf, cm);
}
+ wb_done(&wbc);
}
/* insert wb into fmt */
--- a/roff.h
+++ b/roff.h
@@ -266,8 +266,11 @@
void wb_italiccorrection(struct wb *wb);
void wb_italiccorrectionleft(struct wb *wb);
void wb_cat(struct wb *wb, struct wb *src);
-int wb_hyph(char *word, int *hyidx, int *hywid, int *hydash, int flg);
+void wb_catstr(struct wb *wb, char *beg, char *end);
+int wb_hyphmark(char *word, int *hyidx, int *hyins);
+int wb_hyph(char *word, int *hyidx, int flg);
int wb_wid(struct wb *wb);
+int wb_dashwid(struct wb *wb);
int wb_empty(struct wb *wb);
int wb_eos(struct wb *wb);
void wb_wconf(struct wb *wb, int *ct, int *st, int *sb,
@@ -276,6 +279,8 @@
int wb_kern(struct wb *wb, char *c);
void wb_reset(struct wb *wb);
char *wb_buf(struct wb *wb);
+void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m);
+void wb_fnszset(struct wb *wb, int fn, int sz, int m);
/* character translation (.tr) */
void cmap_add(char *c1, char *c2);
--- a/wb.c
+++ b/wb.c
@@ -416,9 +416,11 @@
char d[ILNLEN];
char *r = *s;
int c;
- wb_reset(w1);
+ if (w1)
+ wb_reset(w1);
while ((c = escread(s, d)) > 0) {
- wb_putc(w1, c, d);
+ if (w1)
+ wb_putc(w1, c, d);
r = *s;
}
if (c < 0 || !strcmp(c_hc, d))
@@ -427,43 +429,37 @@
return 0;
}
-static int wb_dashwid(struct wb *wb)
+/* return the size of \(hy if appended to wb */
+int wb_dashwid(struct wb *wb)
{
struct glyph *g = dev_glyph("hy", R_F(wb));
return charwid(R_F(wb), R_S(wb), g ? g->wid : 0);
}
-/* find the positions marked with dashes, hyphens or \: */
-static int dashpos(char *word, int *hyidx, int *hywid, int *hydash, int flg)
+/* find explicit hyphenation positions: dashes, \: and \% */
+int wb_hyphmark(char *word, int *hyidx, int *hyins)
{
char d[ILNLEN];
- struct wb wb;
char *s = word;
- int n = 0;
- int c;
- wb_init(&wb);
- skipreqs(&s, &wb);
+ int c, n = 0;
+ if (skipreqs(&s, NULL))
+ return -1;
while ((c = escread(&s, d)) >= 0 && n < NHYPHS) {
- wb_putc(&wb, c, d);
- if (c)
- continue;
- hyidx[n] = s - word;
- hywid[n] = wb_wid(&wb);
- hydash[n] = 0;
- if (!strcmp("-", d) || (!strcmp("em", d) ||
- !strcmp("hy", d)) || !strcmp(c_bp, d)) {
- n++;
+ if (!c && !strcmp(c_hc, d)) {
+ hyins[n] = 1;
+ hyidx[n++] = s - word;
}
- if (!strcmp(c_hc, d)) {
- hydash[n] = wb_dashwid(&wb);
- n++;
+ if (!c && (!strcmp(c_bp, d) || !strcmp("-", d) ||
+ (!strcmp("em", d) || !strcmp("hy", d)))) {
+ hyins[n] = 0;
+ hyidx[n++] = s - word;
}
}
- wb_done(&wb);
return n;
}
-static int hyphpos(char *src, int *hyidx, int *hywid, int *hydash, int flg)
+/* find the hyphenation positions of the given word */
+int wb_hyph(char *src, int *hyidx, int flg)
{
char word[ILNLEN]; /* word to pass to hyphenate() */
char hyph[ILNLEN]; /* hyphenation points returned from hyphenate() */
@@ -470,8 +466,6 @@
char *iw[ILNLEN]; /* beginning of i-th char in word */
char *is[ILNLEN]; /* beginning of i-th char in s */
int n = 0; /* the number of characters in word */
- int sw[ILNLEN]; /* dash width at i-th char in word */
- int dw[ILNLEN]; /* dash width at i-th char in word */
int nhy = 0; /* number of hyphenations found */
char d[ILNLEN];
struct wb wb;
@@ -486,8 +480,6 @@
if (c == 0) {
iw[n] = wp;
is[n] = prev_s;
- dw[n] = wb_dashwid(&wb);
- sw[n] = wb_wid(&wb);
/* ignore multi-char aliases except for ligatures */
if (!utf8one(d) && !font_islig(dev_font(R_F(&wb)), d))
strcpy(d, ".");
@@ -501,33 +493,12 @@
if (n < 3)
return 0;
hyphenate(hyph, word, flg);
- for (i = 1; i < n - 1 && nhy < NHYPHS; i++) {
- if (hyph[iw[i] - word]) {
- hyidx[nhy] = is[i] - src;
- hywid[nhy] = sw[i - 1];
- hydash[nhy] = dw[i];
- nhy++;
- }
- }
+ for (i = 1; i < n - 1 && nhy < NHYPHS; i++)
+ if (hyph[iw[i] - word])
+ hyidx[nhy++] = is[i] - src;
return nhy;
}
-int wb_hyph(char *word, int *hyidx, int *hywid, int *hydash, int flg)
-{
- char *s = word;
- struct wb wb;
- int n;
- wb_init(&wb);
- if (skipreqs(&s, &wb)) {
- wb_done(&wb);
- return 0;
- }
- wb_done(&wb);
- if ((n = dashpos(word, hyidx, hywid, hydash, flg)))
- return n;
- return flg ? hyphpos(word, hyidx, hywid, hydash, flg) : 0;
-}
-
void wb_italiccorrection(struct wb *wb)
{
struct glyph *g = wb_prevglyph(wb);
@@ -538,4 +509,26 @@
void wb_italiccorrectionleft(struct wb *wb)
{
wb->icleft_ll = sbuf_len(&wb->sbuf);
+}
+
+void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m)
+{
+ *fn = wb->r_f;
+ *sz = wb->r_s;
+ *m = wb->r_m;
+}
+
+void wb_fnszset(struct wb *wb, int fn, int sz, int m)
+{
+ wb->r_f = fn;
+ wb->r_s = sz;
+ wb->r_m = m;
+}
+
+void wb_catstr(struct wb *wb, char *s, char *end)
+{
+ char d[ILNLEN];
+ int c;
+ while (s < end && (c = escread(&s, d)) >= 0)
+ wb_putc(wb, c, d);
}