6 #define ADJ_LLEN(a) MAX(0, (a)->ll - ((a)->lt >= 0 ? (a)->lt : (a)->li))
10 int wid
; /* word width */
11 int gap
; /* the space before this word */
12 int els_neg
; /* pre-extra line space */
13 int els_pos
; /* post-extra line space */
17 struct word words
[NWORDS
]; /* words in buf */
19 int wid
; /* total width of buf */
20 int swid
; /* current space width */
21 int gap
; /* space before the next word */
22 int nls
; /* newlines before the next word */
23 int l
, i
, t
; /* current .l, .i and ti */
24 int ll
, li
, lt
; /* current line's .l, .i and ti */
27 void adj_ll(struct adj
*adj
, int ll
)
32 void adj_ti(struct adj
*adj
, int ti
)
37 void adj_in(struct adj
*adj
, int in
)
42 /* .ll, .in and .ti are delayed until the partial line is output */
43 static void adj_confupdate(struct adj
*adj
)
51 /* does the adjustment buffer need to be flushed without filling? */
52 static int adj_fullnf(struct adj
*a
)
54 /* blank lines; indented lines; newlines when buffer is empty */
55 return a
->nls
> 1 || (a
->nls
&& a
->gap
) || (a
->nls
&& !a
->nwords
);
58 /* does the adjustment buffer need to be flushed? */
59 int adj_full(struct adj
*a
, int fill
)
65 return a
->wid
> ADJ_LLEN(a
);
68 /* is the adjustment buffer empty? */
69 int adj_empty(struct adj
*a
, int fill
)
71 return !fill
? !a
->nls
: !a
->nwords
&& !adj_fullnf(a
);
75 void adj_swid(struct adj
*adj
, int swid
)
80 /* move n words from the adjustment buffer to s */
81 static int adj_move(struct adj
*a
, int n
, struct sbuf
*s
, int *els_neg
, int *els_pos
)
88 for (i
= 0; i
< n
; i
++) {
90 sbuf_printf(s
, "%ch'%du'", c_ec
, cur
->gap
);
91 sbuf_append(s
, sbuf_buf(&cur
->s
));
93 w
+= cur
->wid
+ cur
->gap
;
94 if (cur
->els_neg
< *els_neg
)
95 *els_neg
= cur
->els_neg
;
96 if (cur
->els_pos
> *els_pos
)
97 *els_pos
= cur
->els_pos
;
102 memmove(a
->words
, a
->words
+ n
, a
->nwords
* sizeof(a
->words
[0]));
104 if (a
->nwords
) /* apply the new .l and .i */
109 /* fill and copy a line into s */
110 int adj_fill(struct adj
*a
, int ad_b
, int fill
, struct sbuf
*s
,
111 int *ll
, int *in
, int *ti
, int *els_neg
, int *els_pos
)
113 int adj_div
, adj_rem
;
116 int llen
= ADJ_LLEN(a
);
120 if (!fill
|| adj_fullnf(a
)) {
122 return adj_move(a
, a
->nwords
, s
, els_neg
, els_pos
);
124 for (n
= 0; n
< a
->nwords
; n
++) {
125 if (n
&& w
+ a
->words
[n
].wid
+ a
->words
[n
].gap
> llen
)
127 w
+= a
->words
[n
].wid
+ a
->words
[n
].gap
;
129 if (ad_b
&& n
> 1 && n
< a
->nwords
) {
130 adj_div
= (llen
- w
) / (n
- 1);
131 adj_rem
= llen
- w
- adj_div
* (n
- 1);
133 for (i
= 0; i
< n
- 1; i
++)
134 a
->words
[i
+ 1].gap
+= adj_div
+ (i
< adj_rem
);
136 w
= adj_move(a
, n
, s
, els_neg
, els_pos
);
138 a
->wid
-= a
->words
[0].gap
;
143 void adj_sp(struct adj
*adj
)
145 adj
->gap
+= adj
->swid
;
148 void adj_nl(struct adj
*adj
)
154 static void adj_word(struct adj
*adj
, struct wb
*wb
)
156 struct word
*cur
= &adj
->words
[adj
->nwords
++];
157 cur
->wid
= wb_wid(wb
);
159 adj
->wid
+= cur
->wid
+ adj
->gap
;
160 wb_getels(wb
, &cur
->els_neg
, &cur
->els_pos
);
162 sbuf_append(&cur
->s
, sbuf_buf(&wb
->sbuf
));
166 /* insert wb into the adjustment buffer */
167 void adj_wb(struct adj
*adj
, struct wb
*wb
)
169 if (wb_empty(wb
) || adj
->nwords
== NWORDS
)
171 if (!adj
->nwords
) /* apply the new .l and .i */
173 if (adj
->nls
&& !adj
->gap
&& adj
->nwords
>= 1)
174 adj
->gap
= adj
->swid
;
180 struct adj
*adj_alloc(void)
182 struct adj
*adj
= malloc(sizeof(*adj
));
183 memset(adj
, 0, sizeof(*adj
));
187 void adj_free(struct adj
*adj
)
192 int adj_wid(struct adj
*adj
)
194 return adj
->wid
+ (adj
->nls
? adj
->swid
: adj
->gap
);