From ebce0cd6c0ceacec630657ae14df6f6110ce0d28 Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Thu, 1 May 2014 11:43:00 +0430 Subject: [PATCH] fmt: preserve current font and size when hyphenating --- fmt.c | 57 ++++++++++++++++++++++++--------------- roff.h | 7 ++++- wb.c | 97 +++++++++++++++++++++++++++++++----------------------------------- 3 files changed, 87 insertions(+), 74 deletions(-) diff --git a/fmt.c b/fmt.c index 9732812..b6c57d0 100644 --- a/fmt.c +++ b/fmt.c @@ -205,36 +205,51 @@ void fmt_newline(struct fmt *f) } } -/* 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 */ diff --git a/roff.h b/roff.h index 2b8cdbc..a4b693e 100644 --- a/roff.h +++ b/roff.h @@ -266,8 +266,11 @@ void wb_drawxend(struct wb *wb); 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_lig(struct wb *wb, char *c); 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); diff --git a/wb.c b/wb.c index bb3dc23..de4f25d 100644 --- a/wb.c +++ b/wb.c @@ -416,9 +416,11 @@ static int skipreqs(char **s, struct wb *w1) 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,51 +429,43 @@ static int skipreqs(char **s, struct wb *w1) 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() */ 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 @@ static int hyphpos(char *src, int *hyidx, int *hywid, int *hydash, int flg) 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 @@ static int hyphpos(char *src, int *hyidx, int *hywid, int *hydash, int flg) 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); @@ -539,3 +510,25 @@ 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); +} -- 2.11.4.GIT