3
* (c) 2002 Mikulas Patocka
4
* This file is a part of the Links program, released under GPL.
17
#define RECT_BOUND_BITS 10 /* --- bound at 1024 pixels */
44
void get_align(char *, int *);
45
void get_valign(char *, int *);
46
void get_c_width(char *, int *, int);
48
void get_align(char *attr, int *a)
51
if ((al = get_attr_val(attr, "align"))) {
52
if (!(strcasecmp(al, "left"))) *a = AL_LEFT;
53
if (!(strcasecmp(al, "right"))) *a = AL_RIGHT;
54
if (!(strcasecmp(al, "center"))) *a = AL_CENTER;
55
if (!(strcasecmp(al, "justify"))) *a = AL_BLOCK;
56
if (!(strcasecmp(al, "char"))) *a = AL_RIGHT; /* NOT IMPLEMENTED */
61
void get_valign(char *attr, int *a)
64
if ((al = get_attr_val(attr, "valign"))) {
65
if (!(strcasecmp(al, "top"))) *a = VAL_TOP;
66
if (!(strcasecmp(al, "middle"))) *a = VAL_MIDDLE;
67
if (!(strcasecmp(al, "bottom"))) *a = VAL_BOTTOM;
68
if (!(strcasecmp(al, "baseline"))) *a = VAL_TOP; /* NOT IMPLEMENTED */
73
void get_c_width(char *attr, int *w, int sh)
76
if ((al = get_attr_val(attr, "width"))) {
77
if (*al && al[strlen(al) - 1] == '*') {
80
al[strlen(al) - 1] = 0;
81
n = strtoul(al, &en, 10);
82
if (n < 10000 && !*en) *w = W_REL - n;
84
int p = get_width(attr, "width", sh);
111
int xpos, ypos, xw, yw;
114
unsigned char bgcolor_str[8];
115
struct g_object_area *root;
116
struct rect_set *brd;
123
struct table_column {
138
int border, cellpd, vcellpd, cellsp;
139
int frame, rules, width, wf;
140
unsigned char *bordercolor;
145
struct table_cell *cells;
147
struct table_column *cols;
155
struct background *bg;
156
struct background *frame_bg;
157
struct rect_set **r_bg;
159
struct rect_set **r_frame;
161
struct table_cell ***r_cells;
168
void free_table(struct table *);
169
void expand_cells(struct table *, int, int);
170
struct table_cell *new_cell(struct table *, int, int);
171
void new_columns(struct table *, int, int, int, int, int);
172
void set_td_width(struct table *, int, int, int);
173
void get_cell_widths(struct table *);
174
void dst_width(int *, int, int, int *);
175
int get_vline_width(struct table *, int);
176
int get_hline_width(struct table *, int);
177
int g_get_vline_pad(struct table *, int, int *, int *);
178
int g_get_hline_pad(struct table *, int, int *, int *);
179
int get_column_widths(struct table *);
180
void get_table_width(struct table *);
181
void distribute_widths(struct table *, int);
182
void check_table_widths(struct table *);
183
void get_table_heights(struct table *);
184
void display_complicated_table(struct table *, int, int, int *);
185
void get_table_frame(struct table *, signed char *, signed char *);
186
void display_table_frames(struct table *, int, int);
188
void add_to_rect_sets(struct rect_set ***, int *, struct rect *);
189
void add_to_cell_sets(struct table_cell ****, int **, int *, struct rect *, struct table_cell *);
190
void table_mouse_event(struct f_data_c *, struct g_object_table *, int, int, int);
191
void draw_rect_set(struct graphics_device *, struct background *, struct rect_set *, int, int);
192
void draw_rect_sets(struct graphics_device *, struct background *, struct rect_set **, int, int, int);
193
void table_draw(struct f_data_c *, struct g_object_table *, int, int);
194
void table_destruct(struct g_object_table *);
195
void table_get_list(struct g_object_table *, void (*)(struct g_object *, struct g_object *));
197
struct table *new_table(void);
199
void get_cell_width(char *, char *, int, int, int, int *, int *, int, int *, unsigned char *);
203
#define CELL(t, x, y) (((x) < 0 || (x) >= (t)->rx || (y) < 0 || (y) >= (t)->ry) ? (internal("accessing cell out of table (%d,%d) - limit (%d,%d)", (x), (y), (t)->rx, (t)->ry), (t)->cells) : &(t)->cells[(y) * (t)->rx + (x)])
205
#define CELL(t, x, y) (&(t)->cells[(y) * (t)->rx + (x)])
208
unsigned char frame_table[81] = {
209
0x00, 0xb3, 0xba, 0xc4, 0xc0, 0xd3, 0xcd, 0xd4, 0xc8,
210
0xc4, 0xd9, 0xbd, 0xc4, 0xc1, 0xd0, 0xcd, 0xd4, 0xc8,
211
0xcd, 0xbe, 0xbc, 0xcd, 0xbe, 0xbc, 0xcd, 0xcf, 0xca,
213
0xb3, 0xb3, 0xba, 0xda, 0xc3, 0xd3, 0xd5, 0xc6, 0xc8,
214
0xbf, 0xb4, 0xbd, 0xc2, 0xc5, 0xd0, 0xd5, 0xc6, 0xc8,
215
0xb8, 0xb5, 0xbc, 0xb8, 0xb5, 0xbc, 0xd1, 0xd8, 0xca,
217
0xba, 0xba, 0xba, 0xd6, 0xd6, 0xc7, 0xc9, 0xc9, 0xcc,
218
0xb7, 0xb7, 0xb6, 0xd2, 0xd2, 0xd7, 0xc9, 0xc9, 0xcc,
219
0xbb, 0xbb, 0xb9, 0xbb, 0xbb, 0xb9, 0xcb, 0xcb, 0xce,
222
unsigned char hline_table[3] = { 0x20, 0xc4, 0xcd };
223
unsigned char vline_table[3] = { 0x20, 0xb3, 0xba };
225
struct table *new_table(void)
228
t = mem_calloc(sizeof(struct table));
243
t->cells = mem_calloc(INIT_X * INIT_Y * sizeof(struct table_cell));
246
t->cols = mem_calloc(INIT_X * sizeof(struct table_column));
249
t->r_heights = DUMMY;
253
void free_table(struct table *t)
258
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
259
struct table_cell *c = CELL(t, i, j);
260
if (c->root) c->root->destruct(c->root);
261
if (c->brd) mem_free(c->brd);
263
for (i = 0; i < t->nr_frame; i++) mem_free(t->r_frame[i]);
264
if (t->r_frame) mem_free(t->r_frame);
265
for (i = 0; i < t->nr_bg; i++) mem_free(t->r_bg[i]);
266
if (t->r_bg) mem_free(t->r_bg);
267
for (i = 0; i < t->nr_cells; i++) mem_free(t->r_cells[i]);
268
mem_free(t->r_cells), mem_free(t->w_cells);
269
if (t->frame_bg) g_release_background(t->frame_bg);
272
if (t->bordercolor) mem_free(t->bordercolor);
273
if (t->min_c) mem_free(t->min_c);
274
if (t->max_c) mem_free(t->max_c);
275
if (t->w_c) mem_free(t->w_c);
276
mem_free(t->r_heights);
283
void expand_cells(struct table *t, int x, int y)
288
for (i = 0; i < t->y; i++) if (CELL(t, t->x - 1, i)->colspan == -1) {
289
for (j = t->x; j <= x; j++) {
290
CELL(t, j, i)->used = 1;
291
CELL(t, j, i)->spanned = 1;
292
CELL(t, j, i)->rowspan = CELL(t, t->x - 1, i)->rowspan;
293
CELL(t, j, i)->colspan = -1;
294
CELL(t, j, i)->mx = CELL(t, t->x - 1, i)->mx;
295
CELL(t, j, i)->my = CELL(t, t->x - 1, i)->my;
303
for (i = 0; i < t->x; i++) if (CELL(t, i, t->y - 1)->rowspan == -1) {
304
for (j = t->y; j <= y; j++) {
305
CELL(t, i, j)->used = 1;
306
CELL(t, i, j)->spanned = 1;
307
CELL(t, i, j)->rowspan = -1;
308
CELL(t, i, j)->colspan = CELL(t, i, t->y - 1)->colspan;
309
CELL(t, i, j)->mx = CELL(t, i, t->y - 1)->mx;
310
CELL(t, i, j)->my = CELL(t, i, t->y - 1)->my;
318
struct table_cell *new_cell(struct table *t, int x, int y)
322
if (x < t->x && y < t->y) goto ret;
324
if (x < t->rx && y < t->ry) {
325
expand_cells(t, x, y);
331
if ((unsigned)nt.rx > MAXINT / 2) overalloc();
335
if ((unsigned)nt.ry > MAXINT / 2) overalloc();
338
if ((unsigned)nt.rx * (unsigned)nt.ry / (unsigned)nt.rx != (unsigned)nt.ry) overalloc();
339
if ((unsigned)nt.rx * (unsigned)nt.ry > MAXINT / sizeof(struct table_cell)) overalloc();
340
nt.cells = mem_calloc(nt.rx * nt.ry * sizeof(struct table_cell));
341
for (i = 0; i < t->x; i++)
342
for (j = 0; j < t->y; j++)
343
memcpy(CELL(&nt, i, j), CELL(t, i, j), sizeof(struct table_cell));
351
return CELL(t, x, y);
354
void new_columns(struct table *t, int span, int width, int align, int valign, int group)
356
if ((unsigned)t->c + (unsigned)span > MAXINT) overalloc();
357
if (t->c + span > t->rc) {
359
struct table_column *nc;
360
while (t->c + span > n) {
361
if ((unsigned)n > MAXINT / 2) overalloc();
364
if ((unsigned)n > MAXINT / sizeof(struct table_column)) overalloc();
365
nc = mem_realloc(t->cols, n * sizeof(struct table_column));
370
t->cols[t->c].align = align;
371
t->cols[t->c].valign = valign;
372
t->cols[t->c].width = width;
373
t->cols[t->c++].group = group;
378
void set_td_width(struct table *t, int x, int width, int f)
381
int n = t->xc ? t->xc : 1;
385
if ((unsigned)n > MAXINT / 2) overalloc();
388
if ((unsigned)n > MAXINT / sizeof(int)) overalloc();
389
nc = mem_realloc(t->xcols, n * sizeof(int));
390
for (i = t->xc; i < n; i++) nc[i] = W_AUTO;
394
if (t->xcols[x] == W_AUTO || f) {
399
if (width == W_AUTO) return;
400
if (width < 0 && t->xcols[x] >= 0) goto set;
401
if (width >= 0 && t->xcols[x] < 0) return;
402
t->xcols[x] = (t->xcols[x] + width) / 2;
405
unsigned char *skip_element(unsigned char *html, unsigned char *eof, unsigned char *what, int sub)
407
int l = strlen(what);
412
while (html < eof && (*html != '<')) rr:html++;
413
if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) {
414
html = skip_comment(html, eof);
417
if (html >= eof) return eof;
418
if (parse_element(html, eof, &name, &namelen, NULL, &html)) goto rr;
419
if (namelen == l && !casecmp(name, what, l) && sub) level++;
420
if (namelen == l + 1 && name[0] == '/' && !casecmp(name + 1, what, l)) if (!--level) return html;
425
unsigned char *s, *e;
428
struct table *parse_table(unsigned char *, unsigned char *, unsigned char **, struct rgb *, int, struct s_e **, int *); /* prototype */
430
struct table *parse_table(unsigned char *html, unsigned char *eof, unsigned char **end, struct rgb *bgcolor, int sh, struct s_e **bad_html, int *bhp)
434
struct table_cell *cell;
435
unsigned char *t_name, *t_attr, *en;
439
unsigned char *lbhp = NULL;
441
int l_val = VAL_MIDDLE;
446
int c_al = AL_TR, c_val = VAL_TR, c_width = W_AUTO, c_span = 0;
447
memcpy(&l_col, bgcolor, sizeof(struct rgb));
453
if (!(t = new_table())) return NULL;
454
memcpy(&t->bgcolor, bgcolor, sizeof(struct rgb));
459
if (bad_html && !p && !lbhp) {
460
if (!(*bhp & (ALLOC_GR-1))) {
461
if ((unsigned)*bhp > MAXINT / sizeof(struct s_e) - ALLOC_GR) overalloc();
462
*bad_html = mem_realloc(*bad_html, (*bhp + ALLOC_GR) * sizeof(struct s_e));
464
lbhp = (*bad_html)[(*bhp)++].s = html;
466
while (html < eof && *html != '<') html++;
468
if (p) CELL(t, x, y)->end = html;
469
if (lbhp) (*bad_html)[*bhp-1].e = html;
472
if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) {
473
html = skip_comment(html, eof);
476
if (parse_element(html, eof, &t_name, &t_namelen, &t_attr, &en)) {
480
if (t_namelen == 5 && !casecmp(t_name, "TABLE", 5)) {
481
en = skip_element(en, eof, "TABLE", 1);
484
if (t_namelen == 6 && !casecmp(t_name, "SCRIPT", 5)) {
485
en = skip_element(en, eof, "SCRIPT", 0);
488
if (t_namelen == 6 && !casecmp(t_name, "/TABLE", 6)) {
489
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
490
if (p) CELL(t, x, y)->end = html;
491
if (lbhp) (*bad_html)[*bhp-1].e = html;
494
if (t_namelen == 8 && !casecmp(t_name, "COLGROUP", 8)) {
495
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
496
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
500
get_align(t_attr, &c_al);
501
get_valign(t_attr, &c_val);
502
get_c_width(t_attr, &c_width, sh);
503
if ((c_span = get_num(t_attr, "span")) == -1) c_span = 1;
506
if (t_namelen == 9 && !casecmp(t_name, "/COLGROUP", 9)) {
507
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
508
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
515
if (t_namelen == 3 && !casecmp(t_name, "COL", 3)) {
517
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
518
if ((sp = get_num(t_attr, "span")) == -1) sp = 1;
522
get_align(t_attr, &al);
523
get_valign(t_attr, &val);
524
get_c_width(t_attr, &wi, sh);
525
new_columns(t, sp, wi, al, val, !!c_span);
529
if (t_namelen == 3 && (!casecmp(t_name, "/TR", 3) || !casecmp(t_name, "/TD", 3) || !casecmp(t_name, "/TH", 3))) {
530
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
531
if (p) CELL(t, x, y)->end = html, p = 0;
532
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
534
if (t_namelen == 2 && !casecmp(t_name, "TR", 2)) {
535
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
536
if (p) CELL(t, x, y)->end = html, p = 0;
537
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
541
memcpy(&l_col, bgcolor, sizeof(struct rgb));
542
get_align(t_attr, &l_al);
543
get_valign(t_attr, &l_val);
544
get_bgcolor(t_attr, &l_col);
548
if (t_namelen == 5 && ((!casecmp(t_name, "THEAD", 5)) || (!casecmp(t_name, "TBODY", 5)) || (!casecmp(t_name, "TFOOT", 5)))) {
549
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
550
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
553
if (t_namelen != 2 || (casecmp(t_name, "TD", 2) && casecmp(t_name, "TH", 2))) goto see;
554
if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
555
if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
556
if (p) CELL(t, x, y)->end = html, p = 0;
557
if (y == -1) y = 0, x = 0;
559
if (!(cell = new_cell(t, x, y))) goto see;
561
if (cell->colspan == -1) goto see;
571
cell->valign = l_val;
574
if (upcase(t_name[1]) == 'H') {
575
unsigned char *e = en;
576
while (e < eof && WHITECHAR(*e)) e++;
577
if (eof - e > 6 && !casecmp(e, "<TABLE", 6)) goto no_th; /* hack for www.root.cz */
579
cell->align = AL_CENTER;
583
if (group == 1) cell->group = 1;
585
if (t->cols[x].align != AL_TR) cell->align = t->cols[x].align;
586
if (t->cols[x].valign != VAL_TR) cell->valign = t->cols[x].valign;
588
memcpy(&cell->bgcolor, &l_col, sizeof(struct rgb));
589
get_align(t_attr, &cell->align);
590
get_valign(t_attr, &cell->valign);
591
get_bgcolor(t_attr, &cell->bgcolor);
593
sprintf(cell->bgcolor_str, "#%02x%02x%02x", cell->bgcolor.r & 0xff, cell->bgcolor.g & 0xff, cell->bgcolor.b & 0xff);
595
if ((csp = get_num(t_attr, "colspan")) == -1) csp = 1;
597
if ((rsp = get_num(t_attr, "rowspan")) == -1) rsp = 1;
599
if (csp >= 0 && rsp >= 0 && csp * rsp > 100000) {
600
if (csp > 10) csp = -1;
601
if (rsp > 10) rsp = -1;
607
get_c_width(t_attr, &w, sh);
608
if (w != W_AUTO) set_td_width(t, x, w, 0);
611
for (i = 1; csp != -1 ? i < csp : x + i < qqq; i++) {
612
struct table_cell *sc;
613
if (!(sc = new_cell(t, x + i, y)) || sc->used) {
615
for (k = 0; k < i; k++) CELL(t, x + k, y)->colspan = csp;
618
sc->used = sc->spanned = 1;
625
for (j = 1; rsp != -1 ? j < rsp : y + j < qqq; j++) {
626
for (k = 0; k < i; k++) {
627
struct table_cell *sc;
628
if (!(sc = new_cell(t, x + k, y + j)) || sc->used) {
630
if (sc->mx == x && sc->my == y) continue;
632
for (l = 0; l < k; l++) memset(CELL(t, x + l, y + j), 0, sizeof(struct table_cell));
634
for (l = 0; l < i; l++) for (m = 0; m < j; m++) CELL(t, x + l, y + m)->rowspan = j;
637
sc->used = sc->spanned = 1;
650
for (x = 0; x < t->x; x++) for (y = 0; y < t->y; y++) {
651
struct table_cell *c = CELL(t, x, y);
653
if (c->colspan == -1) c->colspan = t->x - x;
654
if (c->rowspan == -1) c->rowspan = t->y - y;
658
if ((unsigned)t->y > MAXINT / sizeof(int)) overalloc();
659
t->r_heights = mem_calloc(t->y * sizeof(int));
661
for (x = 0; x < t->c; x++) if (t->cols[x].width != W_AUTO) set_td_width(t, x, t->cols[x].width, 1);
662
set_td_width(t, t->x, W_AUTO, 0);
667
void get_cell_width(char *start, char *end, int cellpd, int w, int a, int *min, int *max, int n_link, int *n_links, unsigned char *bgc)
675
if (n_links) *n_links = n_link;
677
if (!(p = format_html_part(start, end, AL_LEFT, cellpd, w, NULL, !!a, !!a, NULL, n_link))) return;
678
if (min) *min = p->x;
679
if (max) *max = p->xmax;
680
if (n_links) *n_links = p->link_num;
684
if (!(gp = g_format_html_part(start, end, AL_LEFT, 0, w, NULL, n_link, NULL, bgc, NULL))) return;
685
if (min) *min = gp->x;
686
if (max) *max = gp->xmax;
687
if (n_links) *n_links = gp->link_num;
691
/*debug("get_cell_width: %d < %d", *min, *max);*/
692
/*if (min && max && *min > *max) internal("get_cell_width: %d > %d", *min, *max);*/
695
static inline void check_cell_widths(struct table *t)
698
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
700
struct table_cell *c = CELL(t, i, j);
701
if (!c->start) continue;
702
get_cell_width(c->start, c->end, t->cellpd, 0, 0, &min, &max, c->link_num, NULL, gf_val(NULL, c->bgcolor_str));
703
/*if (min != c->min_width || max < c->max_width) internal("check_cell_widths failed");*/
709
struct table_cell *c = cc; \
710
if (!c->start) continue; \
712
get_cell_width(c->start, c->end, t->cellpd, 0, 0, &c->min_width, &c->max_width, nl, &nl, gf_val(NULL, c->bgcolor_str));\
715
void get_cell_widths(struct table *t)
717
int nl = gf_val(t->p->link_num, t->gp->link_num);
719
if (!d_opt->table_order)
720
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) g_c_w(CELL(t, i, j));
722
for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) g_c_w(CELL(t, i, j));
726
void dst_width(int *p, int n, int w, int *lim)
729
for (i = 0; i < n; i++) s += p[i];
736
for (i = 0; i < n; i++) {
738
if (lim && p[i] > lim[i]) w += p[i] - lim[i], p[i] = lim[i];
741
/*if (!lim) internal("bug in dst_width");*/
748
int get_vline_width(struct table *t, int col)
749
{ /* return: -1 none, 0, space, 1 line, 2 double */
753
if (t->rules == R_COLS || t->rules == R_ALL) w = t->cellsp;
754
else if (t->rules == R_GROUPS) w = col < t->c && t->cols[col].group;
755
if (!w && t->cellpd) w = -1;
759
int get_hline_width(struct table *t, int row)
764
if (t->rules == R_ROWS || t->rules == R_ALL) {
766
if (t->cellsp || t->vcellpd) return t->cellsp;
769
else if (t->rules == R_GROUPS) {
771
for (q = 0; q < t->x; q++) if (CELL(t, q, row)->group) goto x;
772
return t->vcellpd ? 0 : -1;
774
if (!w && !t->vcellpd) w = -1;
779
int g_get_vline_pad(struct table *t, int col, int *plpos, int *plsize)
781
int pad, lpos, lsize;
784
if (!col || col == t->x) {
785
border = (!col && t->frame & F_LHS) || (col == t->x && t->frame & F_RHS) ? t->border : 0;
786
pad = border + t->cellsp + t->cellpd;
787
if (!col) lpos = 0, lsize = border + t->cellsp;
788
else lpos = pad - border - t->cellsp, lsize = border + t->cellsp;
790
border = t->rules == R_COLS || t->rules == R_ALL || (t->rules == R_GROUPS && col < t->c && t->cols[col].group) ? t->border : 0;
791
pad = 2 * t->cellpd + t->cellsp;
798
else if (col == t->x) lpos = pad;
801
if (plpos) *plpos = lpos;
802
if (plsize) *plsize = lsize;
806
int g_get_hline_pad(struct table *t, int row, int *plpos, int *plsize)
808
int pad, lpos, lsize;
811
if (!row || row == t->y) {
812
border = (!row && t->frame & F_ABOVE) || (row == t->y && t->frame & F_BELOW) ? t->border : 0;
813
pad = border + t->cellsp + t->cellpd;
814
if (!row) lpos = 0, lsize = border + t->cellsp;
815
else lpos = pad - border - t->cellsp, lsize = border + t->cellsp;
817
border = t->rules == R_ROWS || t->rules == R_ALL ? t->border : 0;
818
if (t->rules == R_GROUPS) {
820
for (q = 0; q < t->x; q++) if (CELL(t, q, row)->group) {
825
pad = 2 * t->cellpd + t->cellsp;
832
else if (row == t->y) lpos = pad;
835
if (plpos) *plpos = lpos;
836
if (plsize) *plsize = lsize;
841
int get_column_widths(struct table *t)
844
if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc();
845
if (!t->min_c) t->min_c = mem_alloc(t->x * sizeof(int));
846
if (!t->max_c) t->max_c = mem_alloc(t->x * sizeof(int));
847
if (!t->w_c) t->w_c = mem_alloc(t->x * sizeof(int));
848
memset(t->min_c, 0, t->x * sizeof(int));
849
memset(t->max_c, 0, t->x * sizeof(int));
853
for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) {
854
struct table_cell *c = CELL(t, i, j);
855
if (c->spanned || !c->used) continue;
856
if (c->colspan + i > t->x) {
857
/*internal("colspan out of table");
861
if (c->colspan == s) {
863
/*int pp = t->max_c[i];*/
865
for (k = 1; k < s; k++) {
866
if (!F) p += get_vline_width(t, i + k) >= 0;
868
else p += g_get_vline_pad(t, i + k, NULL, NULL);
871
dst_width(t->min_c + i, s, c->min_width - p, t->max_c + i);
872
dst_width(t->max_c + i, s, c->max_width - p - m, NULL);
873
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];
874
} else if (c->colspan > s && c->colspan < ns) ns = c->colspan;
876
} while ((s = ns) != MAXINT);
880
void get_table_width(struct table *t)
883
int min = 0, max = 0;
884
for (i = 0; i < t->x; i++) {
885
if (!F) vl = get_vline_width(t, i) >= 0;
888
vl = g_get_vline_pad(t, i, NULL, NULL);
891
min += vl, max += vl;
893
if (t->xcols[i] > t->max_c[i]) max += t->xcols[i];
897
vl = (!!(t->frame & F_LHS) + !!(t->frame & F_RHS)) * !!t->border;
898
min += vl, max += vl;
901
vl = g_get_vline_pad(t, 0, NULL, NULL);
902
min += vl, max += vl;
903
vl = g_get_vline_pad(t, t->x, NULL, NULL);
904
min += vl, max += vl;
909
/*if (min > max) internal("min(%d) > max(%d)", min, max);*/
912
void distribute_widths(struct table *t, int width)
915
int d = width - t->min_t;
923
/*internal("too small width %d, required %d", width, t->min_t);*/
926
for (i = 0; i < t->x; i++) if (t->max_c[i] > mmax_c) mmax_c = t->max_c[i];
927
memcpy(t->w_c, t->min_c, t->x * sizeof(int));
929
if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc();
931
w = mem_alloc(t->x * sizeof(int));
932
mx = mem_alloc(t->x * sizeof(int));
938
memset(w, 0, t->x * sizeof(int));
939
memset(mx, 0, t->x * sizeof(int));
940
for (i = 0; i < t->x; i++) {
943
if (t->w_c[i] < t->xcols[i]) {
944
w[i] = 1, mx[i] = (t->xcols[i] > t->max_c[i] ? t->max_c[i] : t->xcols[i]) - t->w_c[i];
945
if (mx[i] <= 0) w[i] = 0;
949
if (t->xcols[i] < -1 && t->xcols[i] != -2) {
950
w[i] = t->xcols[i] <= -2 ? -2 - t->xcols[i] : 1;
951
mx[i] = t->max_c[i] - t->w_c[i];
952
if (mx[i] <= 0) w[i] = 0;
957
if (t->w_c[i] < t->max_c[i] && (om == 3 || t->xcols[i] == W_AUTO)) {
958
mx[i] = t->max_c[i] - t->w_c[i];
959
if (mmax_c) w[i] = gf_val(5, 5 * HTML_CHAR_WIDTH) + t->max_c[i] * 10 / mmax_c;
964
if (t->xcols[i] >= 0) {
965
w[i] = 1, mx[i] = t->xcols[i] - t->w_c[i];
966
if (mx[i] <= 0) w[i] = 0;
970
if (t->xcols[i] < 0) w[i] = t->xcols[i] <= -2 ? -2 - t->xcols[i] : 1, mx[i] = MAXINT;
973
w[i] = 1, mx[i] = MAXINT;
976
/*internal("could not expand table");*/
986
if (u) memset(u, 0, t->x);
990
for (i = 0; i < t->x; i++) if (w[i]) {
992
if (u && u[i]) continue;
993
if (!(ss = dd * w[i] / p)) ss = 1;
994
if (ss > mx[i]) ss = mx[i];
995
if (ss > mss) mss = ss, mii = i;
1001
d -= t->w_c[mii] - q;
1002
while (d < 0) t->w_c[mii]--, d++;
1003
if (t->w_c[mii] < q) {
1004
/*internal("shrinking cell");*/
1009
} else if (!wq) om++;
1017
#ifdef HTML_TABLE_2ND_PASS
1018
void check_table_widths(struct table *t)
1023
int m, mi = 0; /* go away, warning! */
1024
if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc();
1025
w = mem_calloc(t->x * sizeof(int));
1026
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
1027
struct table_cell *c = CELL(t, i, j);
1029
if (!c->start) continue;
1030
for (k = 1; k < c->colspan; k++) p += get_vline_width(t, i + k) >= 0;
1031
for (k = 0; k < c->colspan; k++) p += t->w_c[i + k];
1032
get_cell_width(c->start, c->end, t->cellpd, p, 1, &c->x_width, NULL, c->link_num, NULL, NULL);
1033
if (c->x_width > p) {
1035
get_cell_width(c->start, c->end, t->cellpd, 0, 0, &min, &max, c->link_num, NULL, NULL);
1036
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);*/
1037
/* sbohem, internale. chytl jsi mi spoustu chyb v tabulkovaci, ale ted je proste cas jit ... ;-( */
1044
for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) {
1045
struct table_cell *c = CELL(t, i, j);
1046
if (!c->start) continue;
1047
if (c->colspan + i > t->x) {
1048
/*internal("colspan out of table");*/
1052
if (c->colspan == s) {
1054
for (k = 1; k < s; k++) p += get_vline_width(t, i + k) >= 0;
1055
dst_width(w + i, s, c->x_width - p, t->max_c + i);
1056
/*for (k = i; k < i + s; k++) if (w[k] > t->w_c[k]) {
1061
for (l = i; l < i + s; l++) if (w[l] < t->w_c[k]) w[l]++, w[k]--, c = 1;
1062
if (w[k] > t->w_c[k]) {
1063
if (!c) internal("can't shrink cell");
1067
} else if (c->colspan > s && c->colspan < ns) ns = c->colspan;
1069
} while ((s = ns) != MAXINT);
1072
for (i = 0; i < t->x; i++) {
1073
s += t->w_c[i], ns += w[i];
1074
/*if (w[i] > t->w_c[i]) {
1076
for (k = 0; k < t->x; k++) debug("%d, %d", t->w_c[k], w[k]);
1077
debug("column %d: new width(%d) is larger than previous(%d)", i, w[i], t->w_c[i]);
1081
/*internal("new width(%d) is larger than previous(%d)", ns, s);*/
1086
for (i = 0; i < t->x; i++) {
1087
/*if (table_level == 1) debug("%d: %d %d %d %d", i, t->max_c[i], t->min_c[i], t->w_c[i], w[i]);*/
1088
if (t->max_c[i] > m) m = t->max_c[i], mi = i;
1090
/*if (table_level == 1) debug("%d %d", mi, s - ns);*/
1093
if (w[mi] <= t->max_c[mi]) {
1103
void get_table_heights(struct table *t)
1107
for (j = 0; j < t->y; j++) {
1108
for (i = 0; i < t->x; i++) {
1109
struct table_cell *cell = CELL(t, i, j);
1115
if (!cell->used || cell->spanned) continue;
1117
fprintf(stderr, "i==%d, w_c[i]==%d, min_c[i]==%d, max_c[i]==%d\n", i, t->w_c[i], t->min_c[i], t->max_c[i]);
1119
for (sp = 0; sp < cell->colspan; sp++) {
1120
xw += t->w_c[i + sp];
1121
if (sp < cell->colspan - 1) {
1122
if (!F) xw += get_vline_width(t, i + sp + 1) >= 0;
1124
else xw += g_get_vline_pad(t, i + sp + 1, NULL, NULL);
1129
if (!(p = format_html_part(cell->start, cell->end, cell->align, t->cellpd, xw, NULL, 2, 2, NULL, cell->link_num))) return;
1130
cell->height = p->y;
1134
if (!(gp = g_format_html_part(cell->start, cell->end, cell->align, 0, xw, NULL, cell->link_num, NULL /* FIX: background image */, cell->bgcolor_str, t->gp->data))) return;
1135
/*if (gp->root->xw > xw) internal("vono to neumi formatovat... buuuu (%d > %d)", gp->root->xw, xw);*/
1136
cell->root = gp->root;
1138
cell->height = gp->y;
1144
/*debug("%d, %d.",xw, cell->height);*/
1150
for (j = 0; j < t->y; j++) {
1151
for (i = 0; i < t->x; i++) {
1152
struct table_cell *cell = CELL(t, i, j);
1153
if (!cell->used || cell->spanned) continue;
1154
if (cell->rowspan == s) {
1156
for (k = 1; k < s; k++) {
1157
if (!F) p += get_hline_width(t, j + k) >= 0;
1159
else p += g_get_hline_pad(t, j + k, NULL, NULL);
1162
dst_width(t->r_heights + j, s, cell->height - p, NULL);
1163
} else if (cell->rowspan > s && cell->rowspan < ns) ns = cell->rowspan;
1166
} while ((s = ns) != MAXINT);
1168
t->rh = (!!(t->frame & F_ABOVE) + !!(t->frame & F_BELOW)) * !!t->border;
1169
for (j = 0; j < t->y; j++) {
1170
t->rh += t->r_heights[j];
1171
if (j) t->rh += get_hline_width(t, j) >= 0;
1176
for (j = 0; j <= t->y; j++) {
1177
t->rh += g_get_hline_pad(t, j, NULL, NULL);
1178
if (j < t->y) t->rh += t->r_heights[j];
1184
void display_complicated_table(struct table *t, int x, int y, int *yy)
1187
struct f_data *f = t->p->data;
1188
int yp, xp = x + ((t->frame & F_LHS) && t->border);
1189
for (i = 0; i < t->x; i++) {
1190
yp = y + ((t->frame & F_ABOVE) && t->border);
1191
for (j = 0; j < t->y; j++) {
1192
struct table_cell *cell = CELL(t, i, j);
1195
struct part *p = NULL;
1196
int xw = 0, yw = 0, s;
1197
for (s = 0; s < cell->colspan; s++) {
1198
xw += t->w_c[i + s];
1199
if (s < cell->colspan - 1) xw += get_vline_width(t, i + s + 1) >= 0;
1201
for (s = 0; s < cell->rowspan; s++) {
1202
yw += t->r_heights[j + s];
1203
if (s < cell->rowspan - 1) yw += get_hline_width(t, j + s + 1) >= 0;
1206
html_top.dontkill = 1;
1207
if (cell->b) format.attr |= AT_BOLD;
1208
memcpy(&format.bg, &cell->bgcolor, sizeof(struct rgb));
1209
memcpy(&par_format.bgcolor, &cell->bgcolor, sizeof(struct rgb));
1210
p = format_html_part(cell->start, cell->end, cell->align, t->cellpd, xw, f, t->p->xp + xp, t->p->yp + yp + (cell->valign != VAL_MIDDLE && cell->valign != VAL_BOTTOM ? 0 : (yw - cell->height) / (cell->valign == VAL_MIDDLE ? 2 : 1)), NULL, cell->link_num);
1215
for (yt = 0; yt < p->y; yt++) {
1216
xxpand_lines(t->p, yp + yt);
1217
xxpand_line(t->p, yp + yt, xp + t->w_c[i]);
1219
kill_html_stack_item(&html_top);
1224
cell->xw = t->w_c[i];
1225
yp += t->r_heights[j];
1226
if (j < t->y - 1) yp += (get_hline_width(t, j + 1) >= 0);
1228
if (i < t->x - 1) xp += t->w_c[i] + (get_vline_width(t, i + 1) >= 0);
1231
for (j = 0; j < t->y; j++) {
1232
yp += t->r_heights[j];
1233
if (j < t->y - 1) yp += (get_hline_width(t, j + 1) >= 0);
1235
*yy = yp + (!!(t->frame & F_ABOVE) + !!(t->frame & F_BELOW)) * !!t->border;
1238
/* !!! FIXME: background */
1239
#define draw_frame_point(xx, yy, ii, jj) \
1240
if (H_LINE_X((ii-1), (jj)) >= 0 || H_LINE_X((ii), (jj)) >= 0 || V_LINE_X((ii), (jj-1)) >= 0 || V_LINE_X((ii), (jj)) >= 0) xset_hchar(t->p, (xx), (yy), frame_table[V_LINE((ii),(jj)-1)+3*H_LINE((ii),(jj))+9*H_LINE((ii)-1,(jj))+27*V_LINE((ii),(jj))], ATTR_FRAME)
1242
#define draw_frame_hline(xx, yy, ll, ii, jj) \
1243
if (H_LINE_X((ii), (jj)) >= 0) xset_hchars(t->p, (xx), (yy), (ll), hline_table[H_LINE((ii), (jj))], ATTR_FRAME)
1245
#define draw_frame_vline(xx, yy, ll, ii, jj) \
1248
if (V_LINE_X((ii), (jj)) >= 0) for (qq = 0; qq < (ll); qq++) xset_hchar(t->p, (xx), (yy) + qq, vline_table[V_LINE((ii), (jj))], ATTR_FRAME); }
1251
#define H_LINE_X(xx, yy) fh[(xx) + 1 + (t->x + 2) * (yy)]
1252
#define V_LINE_X(xx, yy) fv[(yy) + 1 + (t->y + 2) * (xx)]
1254
#define H_LINE_X(xx, yy) (*(xx < -1 || xx > t->x + 1 || yy < 0 || yy > t->y ? (signed char *)NULL : &fh[(xx) + 1 + (t->x + 2) * (yy)]))
1255
#define V_LINE_X(xx, yy) (*(xx < 0 || xx > t->x || yy < -1 || yy > t->y + 1 ? (signed char *)NULL : &fv[(yy) + 1 + (t->y + 2) * (xx)]))
1257
#define H_LINE(xx, yy) (H_LINE_X((xx), (yy)) < 0 ? 0 : H_LINE_X((xx), (yy)))
1258
#define V_LINE(xx, yy) (V_LINE_X((xx), (yy)) < 0 ? 0 : V_LINE_X((xx), (yy)))
1260
void get_table_frame(struct table *t, signed char *fv, signed char *fh)
1263
memset(fh, -1, (t->x + 2) * (t->y + 1));
1264
memset(fv, -1, (t->x + 1) * (t->y + 2));
1265
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
1268
struct table_cell *cell = CELL(t, i, j);
1269
if (!cell->used || cell->spanned) continue;
1270
if ((xsp = cell->colspan) == 0) xsp = t->x - i;
1271
if ((ysp = cell->rowspan) == 0) ysp = t->y - j;
1272
if (t->rules != R_NONE && t->rules != R_COLS) for (x = 0; x < xsp; x++) {H_LINE_X(i + x, j) = t->cellsp; H_LINE_X(i + x, j + ysp) = t->cellsp;}
1273
if (t->rules != R_NONE && t->rules != R_ROWS) for (y = 0; y < ysp; y++) {V_LINE_X(i, j + y) = t->cellsp; V_LINE_X(i + xsp, j + y) = t->cellsp;}
1275
for (x = 0; x < xsp; x++) for (y = 1; y < ysp; y++)
1276
H_LINE_X(i + x, j + y) = -2;
1277
for (x = 1; x < xsp; x++) for (y = 0; y < ysp; y++)
1278
V_LINE_X(i + x, j + y) = -2;
1281
if (t->rules == R_GROUPS) {
1282
for (i = 1; i < t->x; i++) {
1283
if (/*i < t->xc &&*/ t->xcols[i]) continue;
1284
for (j = 0; j < t->y; j++) V_LINE_X(i, j) = 0;
1286
for (j = 1; j < t->y; j++) {
1287
for (i = 0; i < t->x; i++) if (CELL(t, i, j)->group) goto c;
1288
for (i = 0; i < t->x; i++) H_LINE_X(i, j) = 0;
1292
for (i = 0; i < t->x; i++) {
1293
H_LINE_X(i, 0) = t->border * !!(t->frame & F_ABOVE);
1294
H_LINE_X(i, t->y) = t->border * !!(t->frame & F_BELOW);
1296
for (j = 0; j < t->y; j++) {
1297
V_LINE_X(0, j) = t->border * !!(t->frame & F_LHS);
1298
V_LINE_X(t->x, j) = t->border * !!(t->frame & F_RHS);
1302
void display_table_frames(struct table *t, int x, int y)
1304
signed char *fh, *fv;
1307
if ((unsigned)t->x > MAXINT) overalloc();
1308
if ((unsigned)t->y > MAXINT) overalloc();
1309
if (((unsigned)t->x + 2) * ((unsigned)t->y + 2) / ((unsigned)t->x + 2) != ((unsigned)t->y + 2)) overalloc();
1310
if (((unsigned)t->x + 2) * ((unsigned)t->y + 2) > MAXINT) overalloc();
1311
fh = mem_alloc((t->x + 2) * (t->y + 1));
1312
fv = mem_alloc((t->x + 1) * (t->y + 2));
1313
get_table_frame(t, fv, fh);
1316
for (j = 0; j <= t->y; j++) {
1318
if ((j > 0 && j < t->y && get_hline_width(t, j) >= 0) || (j == 0 && t->border && (t->frame & F_ABOVE)) || (j == t->y && t->border && (t->frame & F_BELOW))) {
1319
for (i = 0; i < t->x; i++) {
1321
if (i > 0) w = get_vline_width(t, i);
1322
else w = t->border && (t->frame & F_LHS) ? t->border : -1;
1324
draw_frame_point(cx, cy, i, j);
1325
if (j < t->y) draw_frame_vline(cx, cy + 1, t->r_heights[j], i, j);
1329
draw_frame_hline(cx, cy, w, i, j);
1332
if (t->border && (t->frame & F_RHS)) {
1333
draw_frame_point(cx, cy, i, j);
1334
if (j < t->y) draw_frame_vline(cx, cy + 1, t->r_heights[j], i, j);
1338
} else if (j < t->y) {
1339
for (i = 0; i <= t->x; i++) {
1340
if ((i > 0 && i < t->x && get_vline_width(t, i) >= 0) || (i == 0 && t->border && (t->frame & F_LHS)) || (i == t->x && t->border && (t->frame & F_RHS))) {
1341
draw_frame_vline(cx, cy, t->r_heights[j], i, j);
1344
if (i < t->x) cx += t->w_c[i];
1347
if (j < t->y) cy += t->r_heights[j];
1348
/*for (cyy = cy1; cyy < cy; cyy++) xxpand_line(t->p, cyy, cx - 1);*/
1355
void process_g_table(struct g_part *gp, struct table *t);
1358
void format_table(unsigned char *attr, unsigned char *html, unsigned char *eof, unsigned char **end, void *f)
1360
struct part *p = !F ? f : NULL;
1362
struct g_part *gp = F ? f : NULL;
1364
int border, cellsp, vcellpd, cellpd, align;
1365
int frame, rules, width, wf;
1372
/*int llm = last_link_to_move;*/
1373
struct s_e *bad_html = NULL;
1375
struct node *n, *nn;
1376
int cpd_pass, cpd_width, cpd_last;
1378
memcpy(&bgcolor, &par_format.bgcolor, sizeof(struct rgb));
1379
get_bgcolor(attr, &bgcolor);
1380
if ((border = get_num(attr, "border")) == -1) border = has_attr(attr, "border") || has_attr(attr, "rules") || has_attr(attr, "frame");
1381
/*if (!border) border = 1;*/
1382
if ((cellsp = get_num(attr, "cellspacing")) == -1) cellsp = gf_val(1, 2);
1383
if ((cellpd = get_num(attr, "cellpadding")) == -1) {
1384
vcellpd = gf_val(0, 1);
1385
cellpd = gf_val(!!border, 1);
1388
vcellpd = cellpd >= HTML_CHAR_HEIGHT / 2 + 1;
1389
cellpd = cellpd >= HTML_CHAR_WIDTH / 2 + 1;
1390
} else vcellpd = cellpd;
1392
if (!F && !border) cellsp = 0;
1393
else if (!F && !cellsp) cellsp = 1;
1394
/* Sparc gcc-2.7.2.1 miscompiles this */
1395
do_not_optimize_here(&cellsp);
1396
if (!F && border > 2) border = 2;
1397
if (!F && cellsp > 2) cellsp = 2;
1398
if (F && !cellsp && border) cellsp = 1;
1399
align = par_format.align;
1400
if (align == AL_NO || align == AL_BLOCK) align = AL_LEFT;
1401
if ((al = get_attr_val(attr, "align"))) {
1402
if (!strcasecmp(al, "left")) align = AL_LEFT;
1403
if (!strcasecmp(al, "center")) align = AL_CENTER;
1404
if (!strcasecmp(al, "right")) align = AL_RIGHT;
1408
if ((al = get_attr_val(attr, "frame"))) {
1409
if (!strcasecmp(al, "void")) frame = F_VOID;
1410
if (!strcasecmp(al, "above")) frame = F_ABOVE;
1411
if (!strcasecmp(al, "below")) frame = F_BELOW;
1412
if (!strcasecmp(al, "hsides")) frame = F_HSIDES;
1413
if (!strcasecmp(al, "vsides")) frame = F_VSIDES;
1414
if (!strcasecmp(al, "lhs")) frame = F_LHS;
1415
if (!strcasecmp(al, "rhs")) frame = F_RHS;
1416
if (!strcasecmp(al, "box")) frame = F_BOX;
1417
if (!strcasecmp(al, "border")) frame = F_BOX;
1420
rules = border ? R_ALL : R_NONE;
1421
if ((al = get_attr_val(attr, "rules"))) {
1422
if (!strcasecmp(al, "none")) rules = R_NONE;
1423
if (!strcasecmp(al, "groups")) rules = R_GROUPS;
1424
if (!strcasecmp(al, "rows")) rules = R_ROWS;
1425
if (!strcasecmp(al, "cols")) rules = R_COLS;
1426
if (!strcasecmp(al, "all")) rules = R_ALL;
1429
if (!border) frame = F_VOID;
1431
if ((width = get_width(attr, "width", gf_val(p->data || p->xp, !!gp->data))) == -1) {
1432
width = par_format.width - (par_format.leftmargin + par_format.rightmargin) * gf_val(1, G_HTML_MARGIN);
1433
if (width < 0) width = 0;
1436
if (!(t = parse_table(html, eof, end, &bgcolor, gf_val(p->data || p->xp, !!gp->data), &bad_html, &bad_html_n))) {
1437
if (bad_html) mem_free(bad_html);
1440
for (i = 0; i < bad_html_n; i++) {
1441
while (bad_html[i].s < bad_html[i].e && WHITECHAR(*bad_html[i].s)) bad_html[i].s++;
1442
while (bad_html[i].s < bad_html[i].e && WHITECHAR(bad_html[i].e[-1])) bad_html[i].e--;
1443
if (bad_html[i].s < bad_html[i].e) parse_html(bad_html[i].s, bad_html[i].e, put_chars_f, line_break_f, special_f, gf_val((void *)p, (void *)gp), NULL);
1447
html_top.dontkill = 1;
1448
par_format.align = AL_LEFT;
1457
t->bordercolor = get_attr_val(attr, "bordercolor");
1461
t->vcellpd = vcellpd;
1468
cpd_last = t->cellpd;
1469
cpd_width = 0; /* not needed, but let the warning go away */
1472
if (get_column_widths(t)) goto ret2;
1474
if (gf_val(!p->data && !p->xp, !gp->data)) {
1475
if (!wf && t->max_t > width) t->max_t = width;
1476
if (t->max_t < t->min_t) t->max_t = t->min_t;
1477
if (t->max_t + (par_format.leftmargin + par_format.rightmargin) * gf_val(1, G_HTML_MARGIN) > gf_val(p->xmax, gp->xmax)) *gf_val(&p->xmax, &gp->xmax) = t->max_t + (par_format.leftmargin + par_format.rightmargin) * gf_val(1, G_HTML_MARGIN);
1478
if (t->min_t + (par_format.leftmargin + par_format.rightmargin) * gf_val(1, G_HTML_MARGIN) > gf_val(p->x, gp->x)) *gf_val(&p->x, &gp->x) = t->min_t + (par_format.leftmargin + par_format.rightmargin) * gf_val(1, G_HTML_MARGIN);
1481
if (!F && !cpd_pass && t->min_t > width && t->cellpd) {
1484
cpd_width = t->min_t;
1487
if (cpd_pass == 1 && t->min_t > cpd_width) {
1488
t->cellpd = cpd_last;
1492
/*debug("%d %d %d", t->min_t, t->max_t, width);*/
1493
if (t->min_t >= width) distribute_widths(t, t->min_t);
1494
else if (t->max_t < width && wf) distribute_widths(t, t->max_t);
1495
else distribute_widths(t, width);
1496
if (!F && !p->data && p->xp == 1) {
1497
int ww = t->rw + par_format.leftmargin + par_format.rightmargin;
1498
if (ww > par_format.width) ww = par_format.width;
1499
if (ww < t->rw) ww = t->rw;
1500
if (ww > p->x) p->x = ww;
1504
#ifdef HTML_TABLE_2ND_PASS
1505
if (!F) check_table_widths(t);
1507
get_table_heights(t);
1510
gp->link_num = t->link_num;
1511
process_g_table(gp, t);
1517
x = par_format.leftmargin;
1518
if (align == AL_CENTER) x = (par_format.width + par_format.leftmargin - par_format.rightmargin - t->rw) / 2;
1519
if (align == AL_RIGHT) x = par_format.width - par_format.rightmargin - t->rw;
1520
if (x + t->rw > par_format.width) x = par_format.width - t->rw;
1522
/*display_table(t, x, p->cy, &cye);*/
1524
if (t->rw + par_format.leftmargin + par_format.rightmargin > p->x) p->x = t->rw + par_format.leftmargin + par_format.rightmargin;
1529
n = p->data->nodes.next;
1530
n->yw = p->yp - n->y + p->cy;
1531
display_complicated_table(t, x, p->cy, &cye);
1532
display_table_frames(t, x, p->cy);
1533
nn = mem_alloc(sizeof(struct node));
1535
nn->y = p->yp + cye;
1537
add_to_list(p->data->nodes, nn);
1538
/*if (p->cy + t->rh != cye) internal("size does not match; 1:%d, 2:%d", p->cy + t->rh, cye);*/
1542
*gf_val(&p->link_num, &gp->link_num) = t->link_num;
1546
if (!F) if (p->cy > p->y) p->y = p->cy;
1547
if (t) free_table(t);
1548
kill_html_stack_item(&html_top);
1552
if (!F) free_table_cache();
1554
else g_free_table_cache();
1561
void add_to_rect_sets(struct rect_set ***s, int *n, struct rect *r)
1564
for (i = r->y1 >> RECT_BOUND_BITS; i <= (r->y2 - 1) >> RECT_BOUND_BITS; i++) {
1566
struct rect_set **ns;
1567
if ((unsigned)i > MAXINT / sizeof(struct rect_set *) - 1) overalloc();
1568
ns = mem_realloc(*s, (i + 1) * sizeof(struct rect_set *));
1569
for (j = *n; j < i + 1; j++) ns[j] = init_rect_set();
1573
add_to_rect_set(&(*s)[i], r);
1577
void add_to_cell_sets(struct table_cell ****s, int **nn, int *n, struct rect *r, struct table_cell *c)
1580
for (i = r->y1 >> RECT_BOUND_BITS; i <= (r->y2 - 1) >> RECT_BOUND_BITS; i++) {
1582
struct table_cell ***ns;
1584
if ((unsigned)i > MAXINT / sizeof(struct table_cell ***) - 1) overalloc();
1585
if ((unsigned)i > MAXINT / sizeof(int *) - 1) overalloc();
1586
ns = mem_realloc(*s, (i + 1) * sizeof(struct table_cell ***));
1587
nnn = mem_realloc(*nn, (i + 1) * sizeof(int *));
1588
for (j = *n; j < i + 1; j++) ns[j] = DUMMY, nnn[j] = 0;
1594
struct table_cell **nc;
1595
if ((unsigned)(*nn)[i] > MAXINT / sizeof(struct table_cell *) - 1) overalloc();
1596
nc = mem_realloc((*s)[i], ((*nn)[i] + 1) * sizeof(struct table_cell *));
1604
void table_mouse_event(struct f_data_c *fd, struct g_object_table *o, int x, int y, int b)
1606
struct table *t = o->t;
1608
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
1609
struct table_cell *c = CELL(t, i, j);
1610
if (c->root) if (g_forward_mouse(fd, (struct g_object *)c->root, x, y, b)) return;
1614
void draw_rect_set(struct graphics_device *dev, struct background *bg, struct rect_set *rs, int x, int y)
1617
for (i = 0; i < rs->m; i++) {
1618
struct rect *r = &rs->r[i];
1619
if (is_rect_valid(r))
1620
g_draw_background(dev, bg, x + r->x1, y + r->y1, r->x2 - r->x1, r->y2 - r->y1);
1624
void draw_rect_sets(struct graphics_device *dev, struct background *bg, struct rect_set **rs, int nrs, int x, int y)
1627
for (i = (dev->clip.y1 - y) >> RECT_BOUND_BITS; i <= (dev->clip.y2 - y - 1) >> RECT_BOUND_BITS; i++) if (i >= 0 && i < nrs) {
1628
draw_rect_set(dev, bg, rs[i], x, y);
1632
void table_draw(struct f_data_c *fd, struct g_object_table *o, int x, int y)
1634
static int dgen = 1;
1636
struct table *t = o->t;
1637
struct graphics_device *dev = fd->ses->term->dev;
1640
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
1641
struct table_cell *c = CELL(t, i, j);*/
1643
fprintf(stderr, "Y: %d %d\n", x, y);
1644
fprintf(stderr, "bounds: %d %d\n", dev->clip.y1 + y, dev->clip.y2 + y);
1646
for (i = (dev->clip.y1 - y) >> RECT_BOUND_BITS; i <= (dev->clip.y2 - y - 1) >> RECT_BOUND_BITS; i++) if (i >= 0 && i < t->nr_cells) for (j = 0; j < t->w_cells[i]; j++) {
1647
struct table_cell *c = t->r_cells[i][j];
1648
/*fprintf(stderr, "draw: %d %d\n", i, j);*/
1649
if (c->root && c->dgen != dgen) {
1651
memcpy(&clip, &c->rect, sizeof(struct rect));
1656
if (!do_rects_intersect(&clip, &dev->clip)) continue;
1657
draw_rect_set(dev, c->root->bg, c->brd, x, y);
1658
restrict_clip_area(dev, &clip, x + c->root->x, y + c->root->y, x + c->root->x + c->root->xw/*c->g_width*/, y + c->root->y + c->root->yw);
1659
c->root->draw(fd, c->root, x + c->root->x, y + c->root->y);
1660
drv->set_clip_area(dev, &clip);
1664
draw_rect_sets(dev, t->bg, t->r_bg, t->nr_bg, x, y);
1665
draw_rect_sets(dev, t->frame_bg, t->r_frame, t->nr_frame, x, y);
1668
void table_destruct(struct g_object_table *o)
1674
void table_get_list(struct g_object_table *o, void (*fn)(struct g_object *parent, struct g_object *child))
1676
struct table *t = o->t;
1678
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
1679
struct table_cell *c = CELL(t, i, j);
1680
if (c->root) fn((struct g_object *)o, (struct g_object *)c->root);
1684
void table_bg(struct text_attrib *ta, unsigned char bgstr[8])
1686
if (ta->bg.r + ta->bg.g * 3 + ta->bg.b * 5 > 9 * 128) strcpy(bgstr, "#000000");
1687
else if (ta->fg.r > G_HTML_TABLE_FRAME_COLOR && ta->fg.g > G_HTML_TABLE_FRAME_COLOR && ta->fg.b > G_HTML_TABLE_FRAME_COLOR) {
1688
unsigned char max = ta->fg.r;
1689
if (ta->fg.g > max) max = ta->fg.g;
1690
if (ta->fg.b > max) max = ta->fg.b;
1692
sprintf(bgstr, "#%02x%02x%02x", max, max, max);
1693
} else sprintf(bgstr, "#%02x%02x%02x", G_HTML_TABLE_FRAME_COLOR, G_HTML_TABLE_FRAME_COLOR, G_HTML_TABLE_FRAME_COLOR);
1696
void process_g_table(struct g_part *gp, struct table *t)
1700
struct g_object_table *o;
1701
signed char *fv, *fh;
1702
unsigned char bgstr[8];
1703
struct text_attrib *ta;
1706
for (j = 0; j < t->y; j++) {
1708
y += g_get_hline_pad(t, j, NULL, NULL);
1709
for (i = 0; i < t->x; i++) {
1710
struct table_cell *c;
1711
x += g_get_vline_pad(t, i, NULL, NULL);
1716
for (s = 0; s < c->rowspan; s++) {
1717
yw += t->r_heights[j + s];
1718
if (s < c->rowspan - 1) yw += g_get_hline_pad(t, j + s + 1, NULL, NULL);
1720
c->root->x = x, c->root->y = y;
1721
c->root->y += c->valign != VAL_MIDDLE && c->valign != VAL_BOTTOM ? 0 : (yw - c->root->yw) / (c->valign == VAL_MIDDLE ? 2 : 1);
1725
y += t->r_heights[j];
1728
if (html_top.next != (struct html_element *)(void *)&html_stack) ta = &html_top.next->attr;
1731
if (t->bordercolor && !decode_color(t->bordercolor, &dummy)) {
1732
if (!(t->frame_bg = get_background(NULL, t->bordercolor))) {
1737
table_bg(ta, bgstr);
1738
if (!(t->frame_bg = get_background(NULL, bgstr))) {
1744
if ((unsigned)t->x > MAXINT) overalloc();
1745
if ((unsigned)t->y > MAXINT) overalloc();
1746
if (((unsigned)t->x + 2) * ((unsigned)t->y + 2) / ((unsigned)t->x + 2) != ((unsigned)t->y + 2)) overalloc();
1747
if (((unsigned)t->x + 2) * ((unsigned)t->y + 2) > MAXINT) overalloc();
1748
fh = mem_alloc((t->x + 2) * (t->y + 1));
1749
fv = mem_alloc((t->x + 1) * (t->y + 2));
1750
get_table_frame(t, fv, fh);
1752
for (j = 0; j <= t->y; j++) {
1753
int ypad, ypos, ysize;
1754
ypad = g_get_hline_pad(t, j, &ypos, &ysize);
1756
for (i = 0; i <= t->x; i++) {
1758
int xpad, xpos, xsize;
1759
xpad = g_get_vline_pad(t, i, &xpos, &xsize);
1760
if (i < t->x && j < t->y) {
1761
CELL(t, i, j)->xpos = x + xpos + xsize;
1762
CELL(t, i, j)->ypos = y + ypos + ysize;
1764
if (i > 0 && j > 0) {
1765
struct table_cell *c = CELL(t, i - 1, j - 1);
1766
c->xw = x + xpos - c->xpos;
1767
c->yw = y + ypos - c->ypos;
1768
/*debug("C: %d %d %d %d", c->xpos, c->ypos, c->xw, c->yw);*/
1769
/*debug("%d %d %d", y, ypos, c->ypos);*/
1770
if (!c->used && !c->spanned) {
1771
r.x1 = c->xpos, r.x2 = c->xpos + c->xw;
1772
r.y1 = c->ypos, r.y2 = c->ypos + c->yw;
1773
add_to_rect_sets(&t->r_bg, &t->nr_bg, &r);
1776
r.x1 = x + xpos, r.x2 = x + xpos + xsize;
1777
r.y1 = y + ypos, r.y2 = y + ypos + ysize;
1778
if (H_LINE(i-1,j) || H_LINE(i,j) || V_LINE(i,j-1) || V_LINE(i,j))
1779
add_to_rect_sets(&t->r_frame, &t->nr_frame, &r);
1780
else if (H_LINE_X(i-1,j) != -2 || H_LINE_X(i,j) != -2 || V_LINE_X(i,j-1) != -2 || V_LINE_X(i,j) != -2) add_to_rect_sets(&t->r_bg, &t->nr_bg, &r);
1784
g_get_vline_pad(t, i + 1, &b, NULL);
1786
r.x2 = x + xpad + t->w_c[i] + b;
1789
else if (l > 0) add_to_rect_sets(&t->r_frame, &t->nr_frame, &r);
1790
else add_to_rect_sets(&t->r_bg, &t->nr_bg, &r);
1792
r.x1 = x + xpos, r.x2 = x + xpos + xsize;
1796
g_get_hline_pad(t, j + 1, &b, NULL);
1798
r.y2 = y + ypad + t->r_heights[j] + b;
1801
else if (l > 0) add_to_rect_sets(&t->r_frame, &t->nr_frame, &r);
1802
else add_to_rect_sets(&t->r_bg, &t->nr_bg, &r);
1804
if (i < t->x) x += xpad + t->w_c[i];
1806
if (j < t->y) y += ypad + t->r_heights[j];
1809
for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) {
1810
struct table_cell *c = CELL(t, i, j);
1811
if (c->used && !c->spanned && c->root) {
1812
struct table_cell *d = CELL(t, i + c->colspan - 1, j + c->rowspan - 1);
1816
r.x2 = d->xpos + d->xw;
1817
r.y2 = d->ypos + d->yw;
1818
add_to_cell_sets(&t->r_cells, &t->w_cells, &t->nr_cells, &r, c);
1819
memcpy(&c->rect, &r, sizeof(struct rect));
1820
c->brd = init_rect_set();
1821
/*debug("%d,%d %d,%d", r.x1, r.y1, r.x2, r.y2);*/
1822
add_to_rect_set(&c->brd, &r);
1825
r.x2 = c->root->x + c->root->xw;
1826
r.y2 = c->root->y + c->root->yw;
1827
exclude_rect_from_set(&c->brd, &r);
1828
/*debug("%d,%d %d,%d", r.x1, r.y1, r.x2, r.y2);*/
1835
o = mem_calloc(sizeof(struct g_object_table));
1836
o->mouse_event = table_mouse_event;
1837
o->draw = table_draw;
1838
o->destruct = table_destruct;
1839
o->get_list = table_get_list;
1843
t->bg = gp->root->bg;
1844
flush_pending_text_to_line(gp);
1845
flush_pending_line_to_obj(gp, 0);
1848
add_object_to_line(gp, &gp->line, (struct g_object *)o);
1849
flush_pending_text_to_line(gp);
1850
par_format.align = t->align;
1851
flush_pending_line_to_obj(gp, 0);