html_tbl.c
来自「this is the file used to browse web」· C语言 代码 · 共 1,263 行 · 第 1/3 页
C
1,263 行
get_valign(t_attr, &l_val); get_bgcolor(t_attr, &l_col); y++, x = 0; goto see; } if (t_namelen == 5 && ((!casecmp(t_name, "THEAD", 5)) || (!casecmp(t_name, "TBODY", 5)) || (!casecmp(t_name, "TFOOT", 5)))) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; group = 2; } if (t_namelen != 2 || (casecmp(t_name, "TD", 2) && casecmp(t_name, "TH", 2))) goto see; if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; if (p) CELL(t, x, y)->end = html, p = 0; if (y == -1) y = 0, x = 0; nc: cell = new_cell(t, x, y); if (cell->used) { if (cell->colspan == -1) goto see; x++; goto nc; } cell->mx = x; cell->my = y; cell->used = 1; cell->start = en; p = 1; cell->align = l_al; cell->valign = l_val; if ((cell->b = upcase(t_name[1]) == 'H')) cell->align = AL_CENTER; if (group == 1) cell->group = 1; if (x < t->c) { if (t->cols[x].align != AL_TR) cell->align = t->cols[x].align; if (t->cols[x].valign != VAL_TR) cell->valign = t->cols[x].valign; } memcpy(&cell->bgcolor, &l_col, sizeof(struct rgb)); get_align(t_attr, &cell->align); get_valign(t_attr, &cell->valign); get_bgcolor(t_attr, &cell->bgcolor); if ((csp = get_num(t_attr, "colspan")) == -1) csp = 1; if (!csp) csp = -1; if ((rsp = get_num(t_attr, "rowspan")) == -1) rsp = 1; if (!rsp) rsp = -1; if (csp >= 0 && rsp >= 0 && csp * rsp > 100000) { if (csp > 10) csp = -1; if (rsp > 10) rsp = -1; } cell->colspan = csp; cell->rowspan = rsp; if (csp == 1) { int w = W_AUTO; get_c_width(t_attr, &w, sh); if (w != W_AUTO) set_td_width(t, x, w, 0); } qqq = t->x; for (i = 1; csp != -1 ? i < csp : x + i < qqq; i++) { struct table_cell *sc = new_cell(t, x + i, y); if (sc->used) { csp = i; for (k = 0; k < i; k++) CELL(t, x + k, y)->colspan = csp; break; } sc->used = sc->spanned = 1; sc->rowspan = rsp; sc->colspan = csp; sc->mx = x; sc->my = y; } qqq = t->y; for (j = 1; rsp != -1 ? j < rsp : y + j < qqq; j++) { for (k = 0; k < i; k++) { struct table_cell *sc = new_cell(t, x + k, y + j); if (sc->used) { int l, m; if (sc->mx == x && sc->my == y) continue; /*internal("boo");*/ for (l = 0; l < k; l++) memset(CELL(t, x + l, y + j), 0, sizeof(struct table_cell)); rsp = j; for (l = 0; l < i; l++) for (m = 0; m < j; m++) CELL(t, x + l, y + m)->rowspan = j; goto brk; } sc->used = sc->spanned = 1; sc->rowspan = rsp; sc->colspan = csp; sc->mx = x; sc->my = y; } } brk: goto see; scan_done: *end = html; for (x = 0; x < t->x; x++) for (y = 0; y < t->y; y++) { struct table_cell *c = CELL(t, x, y); if (!c->spanned) { if (c->colspan == -1) c->colspan = t->x - x; if (c->rowspan == -1) c->rowspan = t->y - y; } } if ((unsigned)t->y > MAXINT / sizeof(int)) overalloc(); t->r_heights = mem_alloc(t->y * sizeof(int)); memset(t->r_heights, 0, t->y * sizeof(int)); for (x = 0; x < t->c; x++) if (t->cols[x].width != W_AUTO) set_td_width(t, x, t->cols[x].width, 1); set_td_width(t, t->x, W_AUTO, 0); return t;}void get_cell_width(char *start, char *end, int cellpd, int w, int a, int *min, int *max, int n_link, int *n_links){ struct part *p; if (min) *min = -1; if (max) *max = -1; if (n_links) *n_links = n_link; if (!(p = format_html_part(start, end, AL_LEFT, cellpd, w, NULL, !!a, !!a, NULL, n_link))) return; if (min) *min = p->x; if (max) *max = p->xmax; if (n_links) *n_links = p->link_num; /*if (min && max && *min > *max) internal("get_cell_width: %d > %d", *min, *max);*/ mem_free(p);}static inline void check_cell_widths(struct table *t){ int i, j; for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) { int min, max; struct table_cell *c = CELL(t, i, j); if (!c->start) continue; get_cell_width(c->start, c->end, t->cellpd, 0, 0, &min, &max, c->link_num, NULL); /*if (min != c->min_width || max < c->max_width) internal("check_cell_widths failed");*/ }}#define g_c_w(cc) \do { \ struct table_cell *c = cc; \ if (!c->start) continue; \ c->link_num = nl; \ get_cell_width(c->start, c->end, t->cellpd, 0, 0, &c->min_width, &c->max_width, nl, &nl);\} while (0)void get_cell_widths(struct table *t){ int nl = t->p->link_num; int i, j; if (!d_opt->table_order) for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) g_c_w(CELL(t, i, j)); else for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) g_c_w(CELL(t, i, j)); t->link_num = nl;}void dst_width(int *p, int n, int w, int *lim){ int i, s = 0, d, r; for (i = 0; i < n; i++) s += p[i]; if (s >= w) return; if (!n) return; again: d = (w - s) / n; r = (w - s) % n; w = 0; for (i = 0; i < n; i++) { p[i] += d + (i < r); if (lim && p[i] > lim[i]) w += p[i] - lim[i], p[i] = lim[i]; } if (w) { /*if (!lim) internal("bug in dst_width");*/ lim = NULL; s = 0; goto again; }}int get_vline_width(struct table *t, int col){ /* return: -1 none, 0, space, 1 line, 2 double */ int w = 0; if (!col) return -1; if (t->rules == R_COLS || t->rules == R_ALL) w = t->cellsp; else if (t->rules == R_GROUPS) w = col < t->c && t->cols[col].group; if (!w && t->cellpd) w = -1; return w;}int get_hline_width(struct table *t, int row){ int w = 0; if (!row) return -1; if (t->rules == R_ROWS || t->rules == R_ALL) { x: if (t->cellsp || t->vcellpd) return t->cellsp; return -1; } else if (t->rules == R_GROUPS) { int q; for (q = 0; q < t->x; q++) if (CELL(t, q, row)->group) goto x; return t->vcellpd ? 0 : -1; } if (!w && !t->vcellpd) w = -1; return w;} int get_column_widths(struct table *t){ int i, j, s, ns; if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc(); if (!t->min_c) t->min_c = mem_alloc(t->x * sizeof(int)); if (!t->max_c) t->max_c = mem_alloc(t->x * sizeof(int)); if (!t->w_c) t->w_c = mem_alloc(t->x * sizeof(int)); memset(t->min_c, 0, t->x * sizeof(int)); memset(t->max_c, 0, t->x * sizeof(int)); s = 1; do { ns = MAXINT; for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) { struct table_cell *c = CELL(t, i, j); if (c->spanned || !c->used) continue; if (c->colspan + i > t->x) { /*internal("colspan out of table"); return -1;*/ continue; } if (c->colspan == s) { int k, p = 0; /*int pp = t->max_c[i];*/ int m = 0; for (k = 1; k < s; k++) { p += get_vline_width(t, i + k) >= 0; /*pp += t->max_c[i + k];*/ } /*if (0 && s > 1 && (t->p->data || t->p->xp)) { int d, cc = (!!(t->frame & F_LHS) + !!(t->frame & F_RHS)) * !!t->border; for (d = 0; d < t->c; c++) { cc += t->max_c[d]; if (d > 0) d += get_vline_width(t, d) >= 0; } if (cc >= t->width) goto nd; if (cc + c->max_width - p - pp >= t->width) { m = cc + c->max_width - p - pp - t->width; } }*/ dst_width(t->min_c + i, s, c->min_width - p, t->max_c + i); dst_width(t->max_c + i, s, c->max_width - p - m, NULL); for (k = 0; k < s; k++) if (t->min_c[i + k] > t->max_c[i + k]) t->max_c[i + k] = t->min_c[i + k]; } else if (c->colspan > s && c->colspan < ns) ns = c->colspan; } } while ((s = ns) != MAXINT); return 0;}void get_table_width(struct table *t){ int i, vl; int min = 0, max = 0; for (i = 0; i < t->x; i++) { vl = get_vline_width(t, i) >= 0; min += vl, max += vl; min += t->min_c[i]; if (t->xcols[i] > t->max_c[i]) max += t->xcols[i]; max += t->max_c[i]; } vl = (!!(t->frame & F_LHS) + !!(t->frame & F_RHS)) * !!t->border; min += vl, max += vl; t->min_t = min; t->max_t = max; /*if (min > max) internal("min(%d) > max(%d)", min, max);*/}void distribute_widths(struct table *t, int width){ int i; int d = width - t->min_t; int om = 0; char *u; int *w, *mx; int mmax_c = 0; if (!t->x) return; if (d < 0) { /*internal("too small width %d, required %d", width, t->min_t);*/ return; } for (i = 0; i < t->x; i++) if (t->max_c[i] > mmax_c) mmax_c = t->max_c[i]; memcpy(t->w_c, t->min_c, t->x * sizeof(int)); t->rw = width; if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc(); u = mem_alloc(t->x); w = mem_alloc(t->x * sizeof(int)); mx = mem_alloc(t->x * sizeof(int)); while (d) { int mss, mii; int p = 0; int wq; int dd; memset(w, 0, t->x * sizeof(int)); memset(mx, 0, t->x * sizeof(int)); for (i = 0; i < t->x; i++) { switch (om) { case 0: if (t->w_c[i] < t->xcols[i]) { w[i] = 1, mx[i] = (t->xcols[i] > t->max_c[i] ? t->max_c[i] : t->xcols[i]) - t->w_c[i]; if (mx[i] <= 0) w[i] = 0; } break; case 1: if (t->xcols[i] < -1 && t->xcols[i] != -2) { w[i] = t->xcols[i] <= -2 ? -2 - t->xcols[i] : 1; mx[i] = t->max_c[i] - t->w_c[i]; if (mx[i] <= 0) w[i] = 0; } break; case 2: case 3: if (t->w_c[i] < t->max_c[i] && (om == 3 || t->xcols[i] == W_AUTO)) { mx[i] = t->max_c[i] - t->w_c[i]; if (mmax_c) w[i] = 5 + t->max_c[i] * 10 / mmax_c; else w[i] = 1; } break; case 4: if (t->xcols[i] >= 0) { w[i] = 1, mx[i] = t->xcols[i] - t->w_c[i]; if (mx[i] <= 0) w[i] = 0; } break; case 5: if (t->xcols[i] < 0) w[i] = t->xcols[i] <= -2 ? -2 - t->xcols[i] : 1, mx[i] = MAXINT; break; case 6: w[i] = 1, mx[i] = MAXINT; break; default: /*internal("could not expand table");*/ goto end2; } p += w[i]; } if (!p) { om++; continue; } wq = 0; if (u) memset(u, 0, t->x); dd = d; a: mss = 0; mii = -1; for (i = 0; i < t->x; i++) if (w[i]) { int ss; if (u && u[i]) continue; if (!(ss = dd * w[i] / p)) ss = 1; if (ss > mx[i]) ss = mx[i]; if (ss > mss) mss = ss, mii = i; } if (mii != -1) { int q = t->w_c[mii]; if (u) u[mii] = 1; t->w_c[mii] += mss; d -= t->w_c[mii] - q; while (d < 0) t->w_c[mii]--, d++; if (t->w_c[mii] < q) { /*internal("shrinking cell");*/ t->w_c[mii] = q; } wq = 1; if (d) goto a; } else if (!wq) om++; } end2: mem_free(mx); mem_free(w); if (u) mem_free(u);}#ifdef HTML_TABLE_2ND_PASSvoid check_table_widths(struct table *t){ int *w; int i, j; int s, ns; int m, mi = 0; /* go away, warning! */ if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc(); w = mem_alloc(t->x * sizeof(int)); memset(w, 0, t->x * sizeof(int)); for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) { struct table_cell *c = CELL(t, i, j); int k, p = 0; if (!c->start) continue; for (k = 1; k < c->colspan; k++) p += get_vline_width(t, i + k) >= 0; for (k = 0; k < c->colspan; k++) p += t->w_c[i + k]; get_cell_width(c->start, c->end, t->cellpd, p, 1, &c->x_width, NULL, c->link_num, NULL); if (c->x_width > p) { /*int min, max; get_cell_width(c->start, c->end, t->cellpd, 0, 0, &min, &max, c->link_num, NULL); internal("cell is now wider (%d > %d) min = %d, max = %d, now_min = %d, now_max = %d", c->x_width, p, t->min_c[i], t->max_c[i], min, max);*/ /* sbohem, internale. chytl jsi mi spoustu chyb v tabulkovaci, ale ted je proste cas jit ... ;-( */ c->x_width = p; } } s = 1; do { ns = MAXINT; for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) { struct table_cell *c = CELL(t, i, j); if (!c->start) continue; if (c->colspan + i > t->x) { /*internal("colspan out of table");*/ mem_free(w); return; } if (c->colspan == s) { int k, p = 0; for (k = 1; k < s; k++) p += get_vline_width(t, i + k) >= 0; dst_width(w + i, s, c->x_width - p, t->max_c + i); /*for (k = i; k < i + s; k++) if (w[k] > t->w_c[k]) { int l; int c; ag:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?