+ * Column spacings are needed for span width calculations,
+ * so set the default values now.
+ */
+
+ for (icol = 0; icol <= maxcol; icol++)
+ if (tbl->cols[icol].spacing == SIZE_MAX || icol == maxcol)
+ tbl->cols[icol].spacing = 3;
+
+ /*
+ * Replace the minimum widths with the missing widths,
+ * and dismiss groups that are already wide enough.
+ */
+
+ gp = &first_group;
+ while ((g = *gp) != NULL) {
+ done = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++) {
+ width = tbl->cols[icol].width;
+ if (icol < g->endcol)
+ width += tbl->cols[icol].spacing;
+ if (g->wanted <= width) {
+ done = 1;
+ break;
+ } else
+ (*gp)->wanted -= width;
+ }
+ if (done) {
+ *gp = g->next;
+ free(g);
+ } else
+ gp = &(*gp)->next;
+ }
+
+ colwidth = mandoc_reallocarray(NULL, maxcol + 1, sizeof(*colwidth));
+ while (first_group != NULL) {
+
+ /*
+ * Rebuild the array of the widths of all columns
+ * participating in spans that require expansion.
+ */
+
+ for (icol = 0; icol <= maxcol; icol++)
+ colwidth[icol] = SIZE_MAX;
+ for (g = first_group; g != NULL; g = g->next)
+ for (icol = g->startcol; icol <= g->endcol; icol++)
+ colwidth[icol] = tbl->cols[icol].width;
+
+ /*
+ * Find the smallest and second smallest column width
+ * among the columns which may need expamsion.
+ */
+
+ min1 = min2 = SIZE_MAX;
+ for (icol = 0; icol <= maxcol; icol++) {
+ if (min1 > colwidth[icol]) {
+ min2 = min1;
+ min1 = colwidth[icol];
+ } else if (min1 < colwidth[icol] &&
+ min2 > colwidth[icol])
+ min2 = colwidth[icol];
+ }
+
+ /*
+ * Find the minimum wanted width
+ * for any one of the narrowest columns,
+ * and mark the columns wanting that width.
+ */
+
+ wanted = min2;
+ for (g = first_group; g != NULL; g = g->next) {
+ necol = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++)
+ if (tbl->cols[icol].width == min1)
+ necol++;
+ if (necol == 0)
+ continue;
+ width = min1 + (g->wanted - 1) / necol + 1;
+ if (width > min2)
+ width = min2;
+ if (wanted > width)
+ wanted = width;
+ for (icol = g->startcol; icol <= g->endcol; icol++)
+ if (colwidth[icol] == min1 ||
+ (colwidth[icol] < min2 &&
+ colwidth[icol] > width))
+ colwidth[icol] = width;
+ }
+
+ /* Record the effect of the widening on the group list. */
+
+ gp = &first_group;
+ while ((g = *gp) != NULL) {
+ done = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++) {
+ if (colwidth[icol] != wanted ||
+ tbl->cols[icol].width == wanted)
+ continue;
+ if (g->wanted <= wanted - min1) {
+ done = 1;
+ break;
+ }
+ g->wanted -= wanted - min1;
+ }
+ if (done) {
+ *gp = g->next;
+ free(g);
+ } else
+ gp = &(*gp)->next;
+ }
+
+ /* Record the effect of the widening on the columns. */
+
+ for (icol = 0; icol <= maxcol; icol++)
+ if (colwidth[icol] == wanted)
+ tbl->cols[icol].width = wanted;
+ }
+ free(colwidth);
+
+ /*
+ * Align numbers with text.