ref: 85a9a58654332424c4f865e430c502416f15cdf0
parent: d4a6c339e2825fa9bd57b0c8588096aa623c3bdd
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Apr 17 08:59:29 EDT 2013
adj: add \x
--- a/adj.c
+++ b/adj.c
@@ -4,7 +4,7 @@
#include <string.h>
#include "xroff.h"
-#define ADJ_LL(a) ((a)->ll > (a)->li + (a)->lt ? (a)->ll - (a)->li - (a)->lt : 0)
+#define ADJ_LLEN(a) ((a)->ll > (a)->li + (a)->lt ? (a)->ll - (a)->li - (a)->lt : 0)
struct word {
int beg; /* word beginning offset */
@@ -11,6 +11,8 @@
int end; /* word ending offset */
int wid; /* word width */
int gap; /* the space before this word */
+ int els_neg; /* pre-extra line space */
+ int els_pos; /* post-extra line space */
};
struct adj {
@@ -42,13 +44,6 @@
adj->i = in;
}
-void adj_conf(struct adj *adj, int *ll, int *in, int *ti)
-{
- *ll = adj->ll;
- *in = adj->li;
- *ti = adj->lt;
-}
-
/* .ll, .in and .ti are delayed until the partial line is output */
static void adj_confupdate(struct adj *adj)
{
@@ -72,7 +67,7 @@
return a->nls;
if (adj_fullnf(a))
return 1;
- return !a->word && a->wid > ADJ_LL(a);
+ return !a->word && a->wid > ADJ_LLEN(a);
}
/* is the adjustment buffer empty? */
@@ -88,12 +83,14 @@
}
/* move n words from the adjustment buffer to s */
-static int adj_move(struct adj *a, int n, char *s)
+static int adj_move(struct adj *a, int n, char *s, int *els_neg, int *els_pos)
{
struct word *cur;
int lendiff;
int w = 0;
int i;
+ *els_neg = 0;
+ *els_pos = 0;
for (i = 0; i < n; i++) {
cur = &a->words[i];
s += sprintf(s, "\\h'%du'", cur->gap);
@@ -100,6 +97,10 @@
memcpy(s, a->buf + cur->beg, cur->end - cur->beg);
s += cur->end - cur->beg;
w += cur->wid + cur->gap;
+ if (cur->els_neg < *els_neg)
+ *els_neg = cur->els_neg;
+ if (cur->els_pos > *els_pos)
+ *els_pos = cur->els_pos;
}
*s = '\0';
if (!n)
@@ -120,29 +121,33 @@
}
/* fill and copy a line into s */
-int adj_fill(struct adj *a, int ad_b, int fill, char *s)
+int adj_fill(struct adj *a, int ad_b, int fill, char *s,
+ int *ll, int *in, int *ti, int *els_neg, int *els_pos)
{
int adj_div, adj_rem;
int w = 0;
int i, n;
- int ll = ADJ_LL(a);
+ int llen = ADJ_LLEN(a);
+ *ll = a->ll;
+ *in = a->li;
+ *ti = a->lt;
if (!fill || adj_fullnf(a)) {
a->nls--;
- return adj_move(a, a->nwords, s);
+ return adj_move(a, a->nwords, s, els_neg, els_pos);
}
for (n = 0; n < a->nwords; n++) {
- if (n && w + a->words[n].wid + a->words[n].gap > ll)
+ if (n && w + a->words[n].wid + a->words[n].gap > llen)
break;
w += a->words[n].wid + a->words[n].gap;
}
if (ad_b && n > 1 && n < a->nwords) {
- adj_div = (ll - w) / (n - 1);
- adj_rem = ll - w - adj_div * (n - 1);
- a->wid += ll - w;
+ adj_div = (llen - w) / (n - 1);
+ adj_rem = llen - w - adj_div * (n - 1);
+ a->wid += llen - w;
for (i = 0; i < n - 1; i++)
a->words[i + 1].gap += adj_div + (i < adj_rem);
}
- w = adj_move(a, n, s);
+ w = adj_move(a, n, s, els_neg, els_pos);
if (a->nwords)
a->wid -= a->words[0].gap;
a->words[0].gap = 0;
@@ -156,6 +161,8 @@
adj->word->wid = 0;
adj->word->gap = gap;
adj->wid += gap;
+ adj->word->els_neg = 0;
+ adj->word->els_pos = 0;
}
static void adj_wordend(struct adj *adj)
@@ -196,6 +203,17 @@
va_end(ap);
adj->word->wid += wid;
adj->wid += wid;
+}
+
+/* extra line-space requests */
+void adj_els(struct adj *adj, int els)
+{
+ if (!adj->word)
+ adj_put(adj, 0, "");
+ if (els < adj->word->els_neg)
+ adj->word->els_neg = els;
+ if (els > adj->word->els_pos)
+ adj->word->els_pos = els;
}
struct adj *adj_alloc(void)
--- a/ren.c
+++ b/ren.c
@@ -193,18 +193,14 @@
}
}
-static void out_line(char *out, int w)
+static void out_line(char *out, int w, int ll, int li, int lt)
{
- int prev_d = n_d;
int ljust = 0;
char cmd[32];
- int ll, li, lt, linelen;
- ren_sp(0);
+ int llen = ll - li - lt;
n_n = w;
- adj_conf(cadj, &ll, &li, <);
- linelen = ll - li - lt;
if (n_u && !n_na && (n_j == AD_C || n_j == AD_R))
- ljust = n_j == AD_C ? (linelen - w) / 2 : linelen - w;
+ ljust = n_j == AD_C ? (llen - w) / 2 : llen - w;
if (cdiv) {
if (cdiv->dl < w)
cdiv->dl = w;
@@ -218,19 +214,27 @@
OUT("V%d\n", n_d);
output(out);
}
- if (!ren_traps(prev_d, n_d, 0))
- ren_pagelimit(0);
}
static void ren_br(int force)
{
char out[LNLEN];
- int adj_b, w;
+ int ll, li, lt, els_neg, els_pos;
+ int adj_b, w, prev_d;
ren_first();
if (!adj_empty(cadj, n_u)) {
adj_b = n_u && !n_na && n_j == AD_B;
- w = adj_fill(cadj, !force && adj_b, !force && n_u, out);
- out_line(out, w);
+ w = adj_fill(cadj, !force && adj_b, !force && n_u, out,
+ &ll, &li, <, &els_neg, &els_pos);
+ prev_d = n_d;
+ if (els_neg)
+ ren_sp(-els_neg);
+ ren_sp(0);
+ out_line(out, w, ll, li, lt);
+ if (els_pos)
+ ren_sp(els_pos);
+ if (!ren_traps(prev_d, n_d, 0))
+ ren_pagelimit(0);
}
}
@@ -421,7 +425,7 @@
int l = nextchar(c);
l += nextchar(c + l);
c[l] = '\0';
- } else if (strchr("Dfhsvw", c[0])) {
+ } else if (strchr("Dfhsvwx", c[0])) {
if (c[0] == 'w') {
render_wid();
return 0;
@@ -441,6 +445,8 @@
ren_ps(arg);
if (c[0] == 'v')
adj_put(adj, 0, "\\v'%du'", eval(arg, 0, 'v'));
+ if (c[0] == 'x')
+ adj_els(adj, eval(arg, 0, 'v'));
return 0;
}
}
--- a/xroff.h
+++ b/xroff.h
@@ -171,7 +171,8 @@
struct adj *adj_alloc(void);
void adj_free(struct adj *adj);
-int adj_fill(struct adj *adj, int ad_b, int fill, char *dst);
+int adj_fill(struct adj *adj, int ad_b, int fill, char *dst,
+ int *ll, int *in, int *ti, int *els_neg, int *els_pos);
void adj_put(struct adj *adj, int wid, char *s, ...);
void adj_swid(struct adj *adj, int swid);
int adj_full(struct adj *adj, int fill);
@@ -180,6 +181,7 @@
void adj_ll(struct adj *adj, int ll);
void adj_in(struct adj *adj, int in);
void adj_ti(struct adj *adj, int ti);
+void adj_els(struct adj *adj, int els);
void adj_conf(struct adj *adj, int *ll, int *in, int *ti);
/* builtin number registers; n_X for .X register */