📄 dw_table.c
字号:
/* 2. subtables */ sum_extremes.min_width = (sub->num_subs - 1) * border_spacing; sum_extremes.max_width = (sub->num_subs - 1) * border_spacing; sum_percentage = 0; if (num_cols > 1) for (i = 0; i < sub->num_subs; i++) { Dw_table_sub_get_extremes (&sub->subs[i]); sum_extremes.min_width += sub->subs[i].total_extremes.min_width; sum_extremes.max_width += sub->subs[i].total_extremes.max_width; sum_percentage += sub->subs[i].percentage; if ((sub->use_percentage = use_percentage_map [sub->use_percentage][sub->subs[i].use_percentage]) == -1) sub->use_percentage = (i == 0) ? USE_PERCENTAGE_ALL : USE_PERCENTAGE_SOME; } DEBUG_MSG (DEBUG_EXTR_LEVEL + 1, " sum of subsubs: %d / %d\n", sum_extremes.min_width, sum_extremes.max_width); if (sub->fixed_width) { sum_extremes.max_width = sum_extremes.min_width; sub->span_extremes.max_width = sub->span_extremes.min_width; } sub->total_extremes.min_width = MAX (sum_extremes.min_width, sub->span_extremes.min_width); sub->total_extremes.max_width = MAX (sum_extremes.max_width, sub->span_extremes.max_width); sub->percentage = MAX (sub->percentage, sum_percentage); DEBUG_MSG (DEBUG_EXTR_LEVEL + 1, " final: %d / %d\n", sub->total_extremes.min_width, sub->total_extremes.max_width);}/* * Corrent minima or maxima, used by Dw_table_sub_calc_col_widths. */#define EXTR_VALUE(e) (max ? (e).max_width : (e).min_width)static void Dw_table_sub_adjust_col_widths (DwTableSub *sub, gboolean max, gint32 width, DwExtremes *sub_extremes, gint num_nf_subs, gint num_nf_cols, gint32 sum_nf_sub_widths){ gint i, cols_per_sub, rest_n, rest_w; gint32 sum_sub_widths, sum_orig_sub_widths, sub_extr_width, delta; sum_sub_widths = 0; sum_orig_sub_widths = 0; for (i = 0; i < sub->num_subs; i++) { sum_orig_sub_widths += EXTR_VALUE (sub->subs[i].total_extremes); sum_sub_widths += EXTR_VALUE (sub_extremes[i]); } DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " Comparing %s: total: %d, sum: %d\n", (max ? "max" : "min"), width, sum_sub_widths); if (num_nf_subs == -1) { /* If all subs are fixed, unfix them all. */ sum_nf_sub_widths = sum_sub_widths; num_nf_cols = sub->end_col - sub->start_col; } if (sum_sub_widths < width) { if (sum_nf_sub_widths == 0) { /* All non-fixed columns zero: Apportion the rest to the * non-fixed columns, according to the columns per subtable. */ rest_w = width - sum_sub_widths; rest_n = num_nf_cols; for (i = 0; i < sub->num_subs; i++) { if (num_nf_subs == -1 || !(sub->subs[i].fixed_width || sub->subs[i].use_percentage == USE_PERCENTAGE_ALL)) { cols_per_sub = (sub->subs[i].end_col - sub->subs[i].start_col); sub_extr_width = rest_w * cols_per_sub / rest_n; rest_w -= sub_extr_width; rest_n -= cols_per_sub; EXTR_VALUE (sub_extremes[i]) = sub_extr_width; } } } else { /* Apportion the rest, according to current values. */ rest_w = width - sum_sub_widths; rest_n = sum_nf_sub_widths; for (i = 0; i < sub->num_subs; i++) if (num_nf_subs == -1 || !(sub->subs[i].fixed_width || sub->subs[i].use_percentage == USE_PERCENTAGE_ALL)) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " increasing sub %d: %d -> ", i, EXTR_VALUE (sub_extremes[i])); if (EXTR_VALUE (sub_extremes[i]) > 0) { delta = rest_w * EXTR_VALUE (sub_extremes[i]) / rest_n; rest_w -= delta; rest_n -= EXTR_VALUE (sub_extremes[i]); EXTR_VALUE (sub_extremes[i]) += delta; } DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, "%d\n", EXTR_VALUE (sub_extremes[i])); } } }}/* * Calculate the column widths of a subtable, fill table->width. */static void Dw_table_sub_calc_col_widths (DwTableSub *sub, gint32 width, gint32 total_width){ enum { AT_MIN, AT_MAX, AT_NORM }; /* for sub_status */ gint *sub_status; gint32 avail_width, sub_width, width_norm_cols; gint32 col_width, sum_sub_min_widths, sum_orig_sub_min_widths; gint i, num_cols, cols_per_sub, num_norm_cols, num_nf_subs, num_nf_cols; gint rest_w, rest_n, delta; gboolean success; gint32 border_spacing, diff; DwExtremes extremes, *sub_extremes, sum_nf_sub_extremes; num_cols = sub->end_col - sub->start_col; if (num_cols == 1) { /* single column */ DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " single column at %d: width = %d\n", sub->start_col, width); sub->table->col_width[sub->start_col] = width; } else { /* complex subtable * * The comments "STEP <n>" refer to the documentation in * ../doc/DwTable.txt, "Calculating column widths". Read this * parallel. */ DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " --> complex subtable from %d to %d, width = %d " "(total = %d)\n", sub->start_col, sub->end_col, width, total_width); border_spacing = DW_WIDGET(sub->table)->style->border_spacing; diff = (sub->num_subs - 1) * border_spacing; avail_width = width - diff; extremes = sub->total_extremes; if (width > extremes.max_width) extremes.max_width = width; sub_extremes = g_new (DwExtremes, sub->num_subs); sum_sub_min_widths = 0; /* ---- STEP 1: Calculate relative widths. ---- */ for (i = 0; i < sub->num_subs; i++) { sub_extremes[i] = sub->subs[i].total_extremes; if (sub->subs[i].use_percentage != USE_PERCENTAGE_NO) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " sub %d [%s] has width of %g%% " "-> adjusting: %d/%d -> ", i, sub->subs[i].fixed_width ? "fixed" : "variable", 100 * sub->subs[i].percentage, sub_extremes[i].min_width, sub_extremes[i].max_width); col_width = sub->subs[i].percentage * total_width; if (col_width < sub_extremes[i].min_width) col_width = sub_extremes[i].min_width; sub_extremes[i].min_width = col_width; if (sub->subs[i].use_percentage == USE_PERCENTAGE_ALL) sub_extremes[i].max_width = col_width; DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, "%d/%d\n", sub_extremes[i].min_width, sub_extremes[i].max_width); } else { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " sub %d [%s]: %d/%d\n", i, sub->subs[i].fixed_width ? "fixed" : "variable", sub_extremes[i].min_width, sub_extremes[i].max_width); } sum_sub_min_widths += sub_extremes[i].min_width; } /* ---- STEP 2: Eventually, decrease them again. ---- */ if (sum_sub_min_widths > width) { sum_orig_sub_min_widths = 0; for (i = 0; i < sub->num_subs; i++) sum_orig_sub_min_widths += sub->subs[i].total_extremes.min_width; rest_w = sum_sub_min_widths - (width -diff); rest_n = sum_sub_min_widths - sum_orig_sub_min_widths; for (i = 0; i < sub->num_subs; i++) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " decreasing sub %d: %d -> ", i, sub_extremes[i].min_width); if (sub_extremes[i].min_width != sub->subs[i].total_extremes.min_width) { delta = rest_w * (sub_extremes[i].min_width - sub->subs[i].total_extremes.min_width) / rest_n; rest_w -= delta; rest_n -= (sub_extremes[i].min_width - sub->subs[i].total_extremes.min_width); } else delta = 0; sub_width = sub_extremes[i].min_width - delta; Dw_table_sub_calc_col_widths (&sub->subs[i], sub_width, total_width); DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, "%d\n", sub_width); } } else { /* ---- STEP 3: Eventually, increase the sub-subtable extremes ---- */ num_nf_subs = 0; num_nf_cols = 0; sum_nf_sub_extremes.min_width = 0; sum_nf_sub_extremes.max_width = 0; for (i = 0; i < sub->num_subs; i++) if (!(sub->subs[i].fixed_width || sub->subs[i].use_percentage == USE_PERCENTAGE_ALL)) { num_nf_cols += (sub->subs[i].end_col - sub->subs[i].start_col); num_nf_subs++; sum_nf_sub_extremes.min_width += sub_extremes[i].min_width; sum_nf_sub_extremes.max_width += sub_extremes[i].max_width; } /* If all subtables are fixed, unfix them all. */ if (num_nf_subs == 0) { num_nf_subs = -1; num_nf_cols = num_cols; } Dw_table_sub_adjust_col_widths (sub, FALSE, extremes.min_width, sub_extremes, num_nf_subs, num_nf_cols, sum_nf_sub_extremes.min_width); Dw_table_sub_adjust_col_widths (sub, TRUE, extremes.max_width, sub_extremes, num_nf_subs, num_nf_cols, sum_nf_sub_extremes.max_width); /* ---- STEP 4: Finally, calculate the widths. ---- */ sub_status = g_new (gint, sub->num_subs); /* First, assume that all columns have the same width. */ for (i = 0; i < sub->num_subs; i++) sub_status[i] = AT_NORM; do { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 3, " columns: "); /* Calculate the normal width, and the number of columns at this width. */ width_norm_cols = avail_width; num_norm_cols = num_cols; for (i = 0; i < sub->num_subs; i++) { if (sub_status[i] != AT_NORM) { num_norm_cols -= (sub->subs[i].end_col - sub->subs[i].start_col); if (sub_status[i] == AT_MIN) width_norm_cols -= sub_extremes[i].min_width; else width_norm_cols -= sub_extremes[i].max_width; } DEBUG_MSG (DEBUG_WIDTH_LEVEL + 3, "%c", "ian"[sub_status[i]]); } DEBUG_MSG (DEBUG_WIDTH_LEVEL + 3, "\n"); DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " norm: %d, width = %d\n", num_norm_cols, width_norm_cols); /* * Iteratively, test for minimum/maximum, and correct the * status. As soon as one test fails, the status is * changed, and the iteration starts again from the * beginning. */ success = TRUE; for (i = 0; success && i < sub->num_subs; i++) { cols_per_sub = (sub->subs[i].end_col - sub->subs[i].start_col); switch (sub_status[i]) { case AT_NORM: /* Columns at normal width must between min and max. */ if (width_norm_cols * cols_per_sub < num_norm_cols * sub_extremes[i].min_width) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " sub %d at min\n", i); sub_status[i] = AT_MIN; success = FALSE; } else if (width_norm_cols * cols_per_sub > num_norm_cols * sub_extremes[i].max_width) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " sub %d at max\n", i); sub_status[i] = AT_MAX; success = FALSE; } break; case AT_MIN: /* If the column is at min, the the normal width (which has been changed), must tested against the min. */ if (width_norm_cols * cols_per_sub > num_norm_cols * sub_extremes[i].min_width) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " sub %d at norm\n", i); sub_status[i] = AT_NORM; success = FALSE; } break; case AT_MAX: /* If the column is at max, the the normal width (which has been changed), must tested against the max. */ if (width_norm_cols * cols_per_sub < num_norm_cols * sub_extremes[i].max_width) { DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, " sub %d at norm\n", i); sub_status[i] = AT_NORM; success = FALSE; } break; } } } while (!success); /* ---- STEP 5: Apply calculate the widths. ---- */ rest_n= num_norm_cols; rest_w = width_norm_cols; for (i = 0; i < sub->num_subs; i++) { if (sub_status[i] == AT_MIN) sub_width = sub_extremes[i].min_width; else if (sub_status[i] == AT_MAX) sub_width = sub_extremes[i].max_width; else { cols_per_sub = (sub->subs[i].end_col - sub->subs[i].start_col); sub_width = rest_w * cols_per_sub / rest_n; rest_w -= sub_width; rest_n-= cols_per_sub; } Dw_table_sub_calc_col_widths (&sub->subs[i], sub_width, total_width); } g_free (sub_status); } g_free (sub_extremes); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -