+ rmargin ? (rmargin + sp->opts->cols / 2)
+ / (sp->opts->cols + 1) : 0);
+ if (dp->hspans == 0)
+ continue;
+
+ /*
+ * Build a singly linked list
+ * of all groups of columns joined by spans,
+ * recording the minimum width for each group.
+ */
+
+ gp = &first_group;
+ while (*gp != NULL && ((*gp)->startcol != icol ||
+ (*gp)->endcol != icol + dp->hspans))
+ gp = &(*gp)->next;
+ if (*gp == NULL) {
+ g = mandoc_malloc(sizeof(*g));
+ g->next = *gp;
+ g->wanted = width;
+ g->startcol = icol;
+ g->endcol = icol + dp->hspans;
+ *gp = g;
+ } else if ((*gp)->wanted < width)
+ (*gp)->wanted = width;
+ }
+ }
+
+ /*
+ * The minimum width of columns explicitly specified
+ * in the layout is 1n.
+ */
+
+ if (maxcol < sp_first->opts->cols - 1)
+ maxcol = sp_first->opts->cols - 1;
+ for (icol = 0; icol <= maxcol; icol++) {
+ col = tbl->cols + icol;
+ if (col->width < 1)
+ col->width = 1;
+
+ /*
+ * Column spacings are needed for span width
+ * calculations, so set the default values now.
+ */
+
+ if (col->spacing == SIZE_MAX || icol == maxcol)
+ col->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
+ g->wanted -= width;
+ }
+ if (done) {
+ *gp = g->next;
+ free(g);
+ } else
+ gp = &g->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++) {
+ width = colwidth[icol];
+ if (min1 > width) {
+ min2 = min1;
+ min1 = width;
+ } else if (min1 < width && min2 > width)
+ min2 = width;
+ }
+
+ /*
+ * 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 (colwidth[icol] == min1)
+ necol++;
+ if (necol == 0)
+ continue;
+ width = min1 + (g->wanted - 1) / necol + 1;
+ if (width > min2)
+ width = min2;
+ if (wanted > width)
+ wanted = width;
+ }
+
+ /* Record the effect of the widening. */
+
+ gp = &first_group;
+ while ((g = *gp) != NULL) {
+ done = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++) {
+ if (colwidth[icol] != min1)
+ continue;
+ if (g->wanted <= wanted - min1) {
+ tbl->cols[icol].width += g->wanted;
+ done = 1;
+ break;
+ }
+ tbl->cols[icol].width = wanted;
+ g->wanted -= wanted - min1;
+ }
+ if (done) {
+ *gp = g->next;
+ free(g);
+ } else
+ gp = &g->next;