6 #define ADJ_LLEN(a) MAX(0, (a)->ll - ((a)->lt >= 0 ? (a)->lt : (a)->li))
9 struct wb wbs
[NWORDS
]; /* words in buf */
10 int gaps
[NWORDS
]; /* gaps before words */
12 int wid
; /* total width of buf */
13 int swid
; /* current space width */
14 int gap
; /* space before the next word */
15 int nls
; /* newlines before the next word */
16 int l
, i
, t
; /* current .l, .i and ti */
17 int ll
, li
, lt
; /* current line's .l, .i and ti */
18 int filled
; /* filled all words in the last adj_fill() */
21 void adj_ll(struct adj
*adj
, int ll
)
26 void adj_ti(struct adj
*adj
, int ti
)
31 void adj_in(struct adj
*adj
, int in
)
36 /* .ll, .in and .ti are delayed until the partial line is output */
37 static void adj_confupdate(struct adj
*adj
)
45 /* does the adjustment buffer need to be flushed without filling? */
46 static int adj_fullnf(struct adj
*a
)
48 /* blank lines; indented lines; newlines when buffer is empty */
49 return a
->nls
> 1 || (a
->nls
&& a
->gap
) ||
50 (a
->nls
- a
->filled
> 0 && !a
->nwords
);
53 /* does the adjustment buffer need to be flushed? */
54 int adj_full(struct adj
*a
, int fill
)
57 return a
->nls
- a
->filled
> 0;
60 return a
->nwords
&& a
->wid
> ADJ_LLEN(a
);
63 /* is the adjustment buffer empty? */
64 int adj_empty(struct adj
*a
, int fill
)
66 return !fill
? a
->nls
- a
->filled
<= 0 : !a
->nwords
&& !adj_fullnf(a
);
70 void adj_swid(struct adj
*adj
, int swid
)
75 /* move words inside an adj struct */
76 static void adj_movewords(struct adj
*a
, int dst
, int src
, int len
)
78 memmove(a
->wbs
+ dst
, a
->wbs
+ src
, len
* sizeof(a
->wbs
[0]));
79 memmove(a
->gaps
+ dst
, a
->gaps
+ src
, len
* sizeof(a
->gaps
[0]));
82 static int adj_linewid(struct adj
*a
, int n
)
85 for (i
= 0; i
< n
; i
++)
86 w
+= wb_wid(&a
->wbs
[i
]) + a
->gaps
[i
];
90 static int adj_linefit(struct adj
*a
, int llen
)
93 for (i
= 0; i
< a
->nwords
; i
++) {
94 w
+= wb_wid(&a
->wbs
[i
]) + a
->gaps
[i
];
101 /* move n words from the adjustment buffer to s */
102 static int adj_move(struct adj
*a
, int n
, struct sbuf
*s
, int *els_neg
, int *els_pos
)
109 for (i
= 0; i
< n
; i
++) {
111 sbuf_printf(s
, "%ch'%du'", c_ec
, a
->gaps
[i
]);
112 sbuf_append(s
, sbuf_buf(&cur
->sbuf
));
113 w
+= wb_wid(cur
) + a
->gaps
[i
];
114 if (cur
->els_neg
< *els_neg
)
115 *els_neg
= cur
->els_neg
;
116 if (cur
->els_pos
> *els_pos
)
117 *els_pos
= cur
->els_pos
;
123 adj_movewords(a
, 0, n
, a
->nwords
);
124 a
->wid
= adj_linewid(a
, a
->nwords
);
125 if (a
->nwords
) /* apply the new .l and .i */
130 /* try to hyphenate the n-th word */
131 static void adj_hyph(struct adj
*a
, int n
, int w
, int hyph
)
134 int flg
= hyph
| (n
? 0 : HY_ANY
);
137 if (wb_hyph(&a
->wbs
[n
], w
, &w1
, &w2
, flg
)) {
142 adj_movewords(a
, n
+ 2, n
+ 1, a
->nwords
- n
);
144 memcpy(&a
->wbs
[n
], &w1
, sizeof(w1
));
145 memcpy(&a
->wbs
[n
+ 1], &w2
, sizeof(w2
));
148 a
->wid
= adj_linewid(a
, a
->nwords
);
151 /* fill and copy a line into s */
152 int adj_fill(struct adj
*a
, int ad_b
, int fill
, int hyph
, struct sbuf
*s
,
153 int *ll
, int *in
, int *ti
, int *els_neg
, int *els_pos
)
155 int adj_div
, adj_rem
;
158 int llen
= ADJ_LLEN(a
);
162 if (!fill
|| adj_fullnf(a
)) {
165 return adj_move(a
, a
->nwords
, s
, els_neg
, els_pos
);
167 n
= adj_linefit(a
, llen
);
169 adj_hyph(a
, n
, llen
- adj_linewid(a
, n
) - a
->gaps
[n
], hyph
);
170 n
= adj_linefit(a
, llen
);
173 w
= adj_linewid(a
, n
);
175 adj_div
= (llen
- w
) / (n
- 1);
176 adj_rem
= (llen
- w
) % (n
- 1);
177 for (i
= 0; i
< n
- 1; i
++)
178 a
->gaps
[i
+ 1] += adj_div
+ (i
< adj_rem
);
180 w
= adj_move(a
, n
, s
, els_neg
, els_pos
);
182 a
->wid
-= a
->gaps
[0];
184 a
->filled
= n
&& !a
->nwords
;
188 void adj_sp(struct adj
*adj
)
190 adj
->gap
+= adj
->swid
;
193 void adj_nl(struct adj
*adj
)
199 /* ignore the previous newline */
200 void adj_nonl(struct adj
*adj
)
203 adj
->gap
+= adj
->swid
;
207 static void adj_word(struct adj
*adj
, struct wb
*wb
)
209 int i
= adj
->nwords
++;
210 wb_init(&adj
->wbs
[i
]);
211 adj
->gaps
[i
] = adj
->filled
? 0 : adj
->gap
;
213 adj
->wid
+= wb_wid(wb
) + adj
->gap
;
214 wb_cat(&adj
->wbs
[i
], wb
);
217 /* insert wb into the adjustment buffer */
218 void adj_wb(struct adj
*adj
, struct wb
*wb
)
220 if (wb_empty(wb
) || adj
->nwords
== NWORDS
)
222 if (!adj
->nwords
) /* apply the new .l and .i */
224 if (adj
->nls
&& !adj
->gap
&& adj
->nwords
>= 1)
225 adj
->gap
= adj
->swid
;
231 struct adj
*adj_alloc(void)
233 struct adj
*adj
= malloc(sizeof(*adj
));
234 memset(adj
, 0, sizeof(*adj
));
238 void adj_free(struct adj
*adj
)
243 int adj_wid(struct adj
*adj
)
245 return adj
->wid
+ (adj
->nls
? adj
->swid
: adj
->gap
);