ref: 1c6ab0f6ebf582dd22f9057662e8ac366b7e5c25
parent: 7d5b285d8bbd4b8e90fce45260455a75e1ce463e
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Sep 13 18:45:05 EDT 2016
fmt: support stretchable no-break space (\~) Suggested and tested by aksr <aksr@t-com.me>.
--- a/fmt.c
+++ b/fmt.c
@@ -271,14 +271,14 @@
word->wid = wb_wid(wb);
word->elsn = wb->els_neg;
word->elsp = wb->els_pos;
- word->cost = cost ? wb_cost(wb) : 0;
word->hy = hy ? wb_hywid(wb) : 0;
word->str = str;
word->gap = gap;
+ word->cost = cost;
}
-/* find explicit hyphenation positions: dashes, \: and \% */
-static int fmt_hyphmarks(char *word, int *hyidx, int *hyins)
+/* find explicit break positions: dashes, \:, \%, and \~ */
+static int fmt_hyphmarks(char *word, int *hyidx, int *hyins, int *hygap)
{
char *s = word;
char *d = NULL;
@@ -296,6 +296,10 @@
hyins[n] = 0;
hyidx[n++] = s - word;
}
+ if (!c && !strcmp(c_nb, d)) {
+ hygap[n] = 1;
+ hyidx[n++] = s - word;
+ }
}
return n;
}
@@ -312,8 +316,9 @@
static void fmt_insertword(struct fmt *f, struct wb *wb, int gap)
{
- int hyidx[NHYPHSWORD];
- int hyins[NHYPHSWORD] = {0};
+ int hyidx[NHYPHSWORD]; /* sub-word boundaries */
+ int hyins[NHYPHSWORD] = {0}; /* insert dash */
+ int hygap[NHYPHSWORD] = {0}; /* stretchable no-break space */
char *src = wb_buf(wb);
struct wb wbc;
char *beg;
@@ -320,9 +325,9 @@
char *end;
int n, i;
int cf, cs, cm;
- n = fmt_hyphmarks(src, hyidx, hyins);
+ n = fmt_hyphmarks(src, hyidx, hyins, hygap);
if (n <= 0) {
- fmt_wb2word(f, fmt_mkword(f), wb, 0, 1, gap, 1);
+ fmt_wb2word(f, fmt_mkword(f), wb, 0, 1, gap, wb_cost(wb));
return;
}
/* update f->fillreq considering the new sub-words */
@@ -329,16 +334,23 @@
if (f->fillreq == f->words_n + 1)
f->fillreq += n;
wb_init(&wbc);
+ /* add sub-words */
for (i = 0; i <= n; i++) {
+ int ihy = i < n && hyins[i]; /* dash width */
+ int istr = i == 0 || hygap[i - 1]; /* stretchable */
+ int igap; /* gap width */
+ int icost; /* hyphenation cost */
beg = src + (i > 0 ? hyidx[i - 1] : 0);
end = src + (i < n ? hyidx[i] : strlen(src));
+ if (i < n && hygap[i]) /* remove \~ */
+ end -= strlen(c_nb);
wb_catstr(&wbc, beg, end);
- fmt_wb2word(f, fmt_mkword(f), &wbc,
- i < n && hyins[i], i == 0, i == 0 ? gap : 0, i == n);
- /* restoring wbc */
- wb_fnszget(&wbc, &cs, &cf, &cm);
+ wb_fnszget(&wbc, &cf, &cs, &cm);
+ icost = i == n ? wb_cost(&wbc) : hygap[i] * 10000000;
+ igap = i == 0 ? gap : hygap[i - 1] * font_swid(dev_font(cf), cs, n_ss);
+ fmt_wb2word(f, fmt_mkword(f), &wbc, ihy, istr, igap, icost);
wb_reset(&wbc);
- wb_fnszset(&wbc, cs, cf, cm);
+ wb_fnszset(&wbc, cf, cs, cm); /* restoring wbc */
}
wb_done(&wbc);
}
--- a/roff.h
+++ b/roff.h
@@ -73,6 +73,7 @@
#define c_tc env_tc()
#define c_lc env_lc()
#define c_bp "\\:" /* zero-width word break point */
+#define c_nb "\\~" /* stretchable no-break space */
/* number registers */
#define num_get(id) (*nreg(id))
--- a/wb.c
+++ b/wb.c
@@ -251,6 +251,12 @@
wb_hmov(wb, font_swid(dev_font(R_F(wb)), R_S(wb), n_ss));
return;
}
+ if (!strcmp(c_nb, c)) {
+ wb_flushsub(wb);
+ sbuf_append(&wb->sbuf, c);
+ wb->h += font_swid(dev_font(R_F(wb)), R_S(wb), n_ss);
+ return;
+ }
if (wb_pendingfont(wb) || wb->sub_n == LEN(wb->sub_c))
wb_flush(wb);
if (wb->sub_collect) {