⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tables.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* HTML tables renderer *//* $Id: tables.c,v 1.372.2.3 2005/04/05 21:08:41 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include "elinks.h"#include "document/html/parser/parse.h"#include "document/html/parser/table.h"#include "document/html/parser.h"#include "document/html/renderer.h"#include "document/html/tables.h"#include "document/options.h"#include "terminal/draw.h"#include "util/color.h"#include "util/conv.h"#include "util/error.h"#include "util/memory.h"#include "util/string.h"/* Unsafe macros */#include "document/html/internal.h"struct table_frames {	unsigned int top:1;	unsigned int bottom:1;	unsigned int left:1;	unsigned int right:1;};static voidget_table_frames(struct table *table, struct table_frames *result){	assert(table && result);	if (table->border) {		result->top = !!(table->frame & TABLE_FRAME_ABOVE);		result->bottom = !!(table->frame & TABLE_FRAME_BELOW);		result->left = !!(table->frame & TABLE_FRAME_LHS);		result->right = !!(table->frame & TABLE_FRAME_RHS);	} else {		memset(result, 0, sizeof(*result));	}}/* Distance of the table from the left margin. */static intget_table_indent(struct table *table){	int width = par_format.width - table->real_width;	int indent;	switch (table->align) {	case ALIGN_CENTER:		indent = (width + par_format.leftmargin - par_format.rightmargin) / 2;		break;	case ALIGN_RIGHT:		indent = width - par_format.rightmargin;		break;	case ALIGN_LEFT:	case ALIGN_JUSTIFY:	default:		indent = par_format.leftmargin;	}	/* Don't use int_bounds(&x, 0, width) here,	 * width may be < 0. --Zas */	if (indent > width) indent = width;	if (indent < 0) indent = 0;	return indent;}static inline struct part *format_cell(struct table *table, struct table_cell *cell,	    struct document *document, int x, int y, int width){	if (document) {		x += table->part->box.x;		y += table->part->box.y;	}	return format_html_part(cell->start, cell->end, cell->align,				table->cellpadding, width, document, x, y,				NULL, cell->link_num);}static inline voidget_cell_width(unsigned char *start, unsigned char *end,	       int cellpadding, int width,	       int a, int *min, int *max,	       int link_num, int *new_link_num){	struct part *part;	if (min) *min = -1;	if (max) *max = -1;	if (new_link_num) *new_link_num = link_num;	part = format_html_part(start, end, ALIGN_LEFT, cellpadding, width, NULL,				!!a, !!a, NULL, link_num);	if (!part) return;	if (min) *min = part->box.width;	if (max) *max = part->max_width;	if (new_link_num) *new_link_num = part->link_num;	if (min && max) {		assertm(*min <= *max, "get_cell_width: %d > %d", *min, *max);	}	mem_free(part);}static voidget_cell_widths(struct table *table){	int link_num = table->part->link_num;	if (!global_doc_opts->table_order) {		int col, row;		for (row = 0; row < table->rows; row++)			for (col = 0; col < table->cols; col++) {				struct table_cell *cell = CELL(table, col, row);				if (!cell->start) continue;				cell->link_num = link_num;				get_cell_width(cell->start, cell->end, table->cellpadding, 0, 0,					       &cell->min_width, &cell->max_width,					       link_num, &link_num);			}	} else {		int col, row;		for (col = 0; col < table->cols; col++)			for (row = 0; row < table->rows; row++) {				struct table_cell *cell = CELL(table, col, row);				if (!cell->start) continue;				cell->link_num = link_num;				get_cell_width(cell->start, cell->end, table->cellpadding, 0, 0,					       &cell->min_width, &cell->max_width,					       link_num, &link_num);			}	}	table->link_num = link_num;}static inline voiddistribute_values(int *values, int count, int wanted, int *limits){	int i;	int sum = 0, d, r, t;	for (i = 0; i < count; i++) sum += values[i];	if (sum >= wanted) return;again:	t = wanted - sum;	d = t / count;	r = t % count;	wanted = 0;	if (limits) {		for (i = 0; i < count; i++) {			int delta;			values[i] += d + (i < r);			delta = values[i] - limits[i];			if (delta > 0) {				wanted += delta;				values[i] = limits[i];			}		}	} else {		for (i = 0; i < count; i++) {			values[i] += d + (i < r);		}	}	if (wanted) {		assertm(limits, "bug in distribute_values()");		limits = NULL;		sum = 0;		goto again;	}}/* Returns: -1 none, 0, space, 1 line, 2 double */static inline intget_vline_width(struct table *table, int col){	int width = 0;	if (!col) return -1;	if (table->rules == TABLE_RULE_COLS || table->rules == TABLE_RULE_ALL)		width = table->cellspacing;	else if (table->rules == TABLE_RULE_GROUPS)		width = (col < table->columns_count && table->columns[col].group);	if (!width && table->cellpadding) width = -1;	return width;}static intget_hline_width(struct table *table, int row){	if (!row) return -1;	if (table->rules == TABLE_RULE_ROWS || table->rules == TABLE_RULE_ALL) {		if (table->cellspacing || table->vcellpadding)			return table->cellspacing;		return -1;	} else if (table->rules == TABLE_RULE_GROUPS) {		int col;		for (col = 0; col < table->cols; col++)			if (CELL(table, col, row)->is_group) {				if (table->cellspacing || table->vcellpadding)					return table->cellspacing;				return -1;			}	}	return table->vcellpadding ? 0 : -1;}#define has_vline_width(table, col) (get_vline_width(table, col) >= 0)#define has_hline_width(table, row) (get_hline_width(table, row) >= 0)static intget_column_widths(struct table *table){	int colspan;	if (!table->cols) return -1; /* prevents calloc(0, ...) calls */	if (!table->min_cols_widths) {		table->min_cols_widths = mem_calloc(table->cols, sizeof(*table->min_cols_widths));		if (!table->min_cols_widths) return -1;	}	if (!table->max_cols_widths) {		table->max_cols_widths = mem_calloc(table->cols, sizeof(*table->max_cols_widths));		if (!table->max_cols_widths) {			mem_free_set(&table->min_cols_widths, NULL);			return -1;		}	}	if (!table->cols_widths) {		table->cols_widths = mem_calloc(table->cols, sizeof(*table->cols_widths));		if (!table->cols_widths) {			mem_free_set(&table->min_cols_widths, NULL);			mem_free_set(&table->max_cols_widths, NULL);			return -1;		}	}	colspan = 1;	do {		int col, row;		int new_colspan = INT_MAX;		for (col = 0; col < table->cols; col++)	for (row = 0; row < table->rows; row++) {			struct table_cell *cell = CELL(table, col, row);			if (cell->is_spanned || !cell->is_used) continue;			assertm(cell->colspan + col <= table->cols, "colspan out of table");			if_assert_failed return -1;			if (cell->colspan == colspan) {				int k, p = 0;				for (k = 1; k < colspan; k++)					p += has_vline_width(table, col + k);				distribute_values(&table->min_cols_widths[col],						  colspan,						  cell->min_width - p,						  &table->max_cols_widths[col]);				distribute_values(&table->max_cols_widths[col],						  colspan,						  cell->max_width - p,						  NULL);				for (k = 0; k < colspan; k++) {					int tmp = col + k;					int_lower_bound(&table->max_cols_widths[tmp],							table->min_cols_widths[tmp]);				}			} else if (cell->colspan > colspan				   && cell->colspan < new_colspan) {				new_colspan = cell->colspan;			}		}		colspan = new_colspan;	} while (colspan != INT_MAX);	return 0;}static voidget_table_width(struct table *table){	struct table_frames table_frames;	int min = 0;	int max = 0;	int col;	for (col = 0; col < table->cols; col++) {		int vl = has_vline_width(table, col);		min += vl + table->min_cols_widths[col];		max += vl + table->max_cols_widths[col];		if (table->cols_x[col] > table->max_cols_widths[col])			max += table->cols_x[col];	}	get_table_frames(table, &table_frames);	table->min_width = min + table_frames.left + table_frames.right;	table->max_width = max + table_frames.left + table_frames.right;	assertm(min <= max, "min(%d) > max(%d)", min, max);	/* XXX: Recovery path? --pasky */}/* Initialize @width and @max_width arrays depending on the @stretch_method */static inline intapply_stretch_method(struct table *table, int widths[], int max_widths[],		     int stretch_method, int max_cols_width){	int col, total_width = 0;	for (col = 0; col < table->cols; col++) {		switch (stretch_method) {		case 0:			if (table->cols_widths[col] >= table->cols_x[col])				break;			widths[col] = 1;			max_widths[col] = int_min(table->cols_x[col],						  table->max_cols_widths[col])					  - table->cols_widths[col];			if (max_widths[col] <= 0) widths[col] = 0;			break;		case 1:			if (table->cols_x[col] > WIDTH_RELATIVE)				break;			widths[col] = WIDTH_RELATIVE - table->cols_x[col];			max_widths[col] = table->max_cols_widths[col]					  - table->cols_widths[col];			if (max_widths[col] <= 0) widths[col] = 0;			break;		case 2:			if (table->cols_x[col] != WIDTH_AUTO)				break;			/* Fall-through */		case 3:			if (table->cols_widths[col] >= table->max_cols_widths[col])				break;			max_widths[col] = table->max_cols_widths[col]					  - table->cols_widths[col];			if (max_cols_width) {				widths[col] = 5 + table->max_cols_widths[col] * 10 / max_cols_width;			} else {				widths[col] = 1;			}			break;		case 4:			if (table->cols_x[col] < 0)				break;			widths[col] = 1;			max_widths[col] = table->cols_x[col]					  - table->cols_widths[col];			if (max_widths[col] <= 0) widths[col] = 0;			break;		case 5:			if (table->cols_x[col] >= 0)				break;			if (table->cols_x[col] <= WIDTH_RELATIVE) {				widths[col] = WIDTH_RELATIVE - table->cols_x[col];			} else {				widths[col] = 1;			}			max_widths[col] = INT_MAX;			break;		case 6:			widths[col] = 1;			max_widths[col] = INT_MAX;			break;		default:			return -1;		}		total_width += widths[col];	}	return total_width;}/* Stretches the table columns by distributed the @spare_width among them. * Returns how much of @spare_width was actually distributed. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -