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 + -
显示快捷键?