ref: d7d272b68072acd84a344aa8351230c41edf311b
parent: 05ce05cf03e9a81cfa8b65f45e91739d83741fe3
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat May 10 04:47:16 EDT 2014
fmt: shrink word spaces with .ssh request The new .ssh request specifies the amount (in percentage) by which word spaces may be shrinked while filling. The default value is zero.
--- a/fmt.c
+++ b/fmt.c
@@ -120,7 +120,7 @@
return beg < end ? w + f->words[end - 1].hy : 0;
}
-/* the number stretchable spaces in f */
+/* the number of stretchable spaces in f */
static int fmt_spaces(struct fmt *f, int beg, int end)
{
int i, n = 0;
@@ -130,6 +130,16 @@
return n;
}
+/* the amount of stretchable spaces in f */
+static int fmt_spacessum(struct fmt *f, int beg, int end)
+{
+ int i, n = 0;
+ for (i = beg + 1; i < end; i++)
+ if (f->words[i].str)
+ n += f->words[i].gap;
+ return n;
+}
+
/* return the next line in the buffer */
int fmt_nextline(struct fmt *f, struct sbuf *sbuf, int *w,
int *li, int *ll, int *els_neg, int *els_pos)
@@ -307,7 +317,8 @@
{
int i, pen = 0;
long cur;
- int lwid = 0;
+ int lwid = 0; /* current line length */
+ int swid = 0; /* amount of spaces */
int llen = MAX(1, FMT_LLEN(f));
if (pos <= 0)
return 0;
@@ -323,8 +334,11 @@
lwid += f->words[i].wid;
if (i + 1 < pos)
lwid += f->words[i + 1].gap;
- if (lwid > llen && pos - i > 1)
- break;
+ if (i + 1 < pos && f->words[i + 1].str)
+ swid += f->words[i + 1].gap;
+ if (lwid - (swid * n_ssh / 100) > llen)
+ if (pos - i > 1)
+ break;
cur = fmt_findcost(f, i) + FMT_COST(lwid, llen, pen);
if (f->best_pos[pos] < 0 || cur < f->best[pos]) {
f->best_pos[pos] = i;
@@ -409,6 +423,10 @@
if (FMT_ADJ(f) && nspc) {
fmt_div = (llen - w) / nspc;
fmt_rem = (llen - w) % nspc;
+ if (fmt_rem < 0) {
+ fmt_div--;
+ fmt_rem += nspc;
+ }
for (i = beg + 1; i < end; i++)
if (f->words[i].str)
f->words[i].gap += fmt_div + (fmt_rem-- > 0);
@@ -433,12 +451,14 @@
int end; /* the final line ends before this word */
int end_head; /* like end, but only the first nreq lines included */
int head = 0; /* only nreq first lines have been formatted */
+ int llen; /* line length, taking shrinkable spaces into account */
int n, i;
if (!FMT_FILL(f))
return 0;
+ llen = fmt_wordslen(f, 0, f->nwords) -
+ fmt_spacessum(f, 0, f->nwords) * n_ssh / 100;
/* not enough words to fill */
- if ((f->fillreq <= 0 || f->nwords < f->fillreq) &&
- fmt_wordslen(f, 0, f->nwords) <= FMT_LLEN(f))
+ if ((f->fillreq <= 0 || f->nwords < f->fillreq) && llen <= FMT_LLEN(f))
return 0;
nreq = (n_hy & HY_LAST) ? fmt_safelines() : 0;
if (nreq > 0 && nreq <= fmt_nlines(f))
--- a/reg.c
+++ b/reg.c
@@ -36,7 +36,7 @@
".nS", ".m", ".s", ".u", ".v",
".it", ".itn", ".mc", ".mcn",
".ce", ".f0", ".hy", ".hyp", ".i0", ".l0",
- ".L0", ".m0", ".n0", ".s0", ".ss",
+ ".L0", ".m0", ".n0", ".s0", ".ss", ".ssh",
".ti", ".lt", ".lt0", ".v0",
};
--- a/roff.h
+++ b/roff.h
@@ -468,6 +468,7 @@
#define n_ns (*nreg(map(".ns"))) /* .ns mode */
#define n_o0 (*nreg(map(".o0"))) /* last .o */
#define n_ss (*nreg(map(".ss"))) /* .ss value */
+#define n_ssh (*nreg(map(".ssh"))) /* .ssh value; word space compression */
#define n_s0 (*nreg(map(".s0"))) /* last .s */
#define n_sv (*nreg(map(".sv"))) /* .sv value */
#define n_lt (*nreg(map(".lt"))) /* .lt value */
--- a/tr.c
+++ b/tr.c
@@ -424,6 +424,11 @@
n_ss = eval_re(args[1], n_ss, 0);
}
+static void tr_ssh(char **args)
+{
+ n_ssh = args[1] ? eval_re(args[1], n_ssh, 0) : 0;
+}
+
static void tr_cs(char **args)
{
if (!args[1])
@@ -902,6 +907,7 @@
{"so", tr_so},
{"sp", tr_sp},
{"ss", tr_ss},
+ {"ssh", tr_ssh},
{"sv", tr_sv},
{"sy", tr_sy, mkargs_eol},
{"ta", tr_ta},