1
/* $Id: table.c,v 1.58 2010/08/09 11:59:19 htrb Exp $ */
11
#include "parsetagx.h"
16
int symbol_width0 = 0;
18
#define RULE_WIDTH symbol_width
19
#define RULE(mode,n) (((mode) == BORDER_THICK) ? ((n) + 16) : (n))
20
#define TK_VERTICALBAR(mode) RULE(mode,5)
23
#define BORDERHEIGHT 1
24
#define NOBORDERWIDTH 1
25
#define NOBORDERHEIGHT 0
29
#define HTT_ALIGN 0x30
31
#define HTT_CENTER 0x10
32
#define HTT_RIGHT 0x20
33
#define HTT_TRSET 0x40
34
#define HTT_VALIGN 0x700
36
#define HTT_MIDDLE 0x200
37
#define HTT_BOTTOM 0x400
38
#define HTT_VTRSET 0x800
42
#define TAG_IS(s,tag,len) (strncasecmp(s,tag,len)==0&&(s[len] == '>' || IS_SPACE((int)s[len])))
45
#define max(a,b) ((a) > (b) ? (a) : (b))
48
#define min(a,b) ((a) > (b) ? (b) : (a))
51
#define abs(a) ((a) >= 0. ? (a) : -(a))
54
#define set_prevchar(x,y,n) Strcopy_charp_n((x),(y),(n))
55
#define set_space_to_prevchar(x) Strcopy_charp_n((x)," ",1)
60
#endif /* not MESCHACH */
64
int correct_table_matrix(struct table *, int, int, int, double);
65
void set_table_matrix(struct table *, int);
76
return COLS * (log((double)x / COLS) + 1.);
82
return (double)a / COLS * 4 + 1.;
85
#define sigma_td(a) (0.5*weight2(a)) /* <td width=...> */
86
#define sigma_td_nw(a) (32*weight2(a)) /* <td ...> */
87
#define sigma_table(a) (0.25*weight2(a)) /* <table width=...> */
88
#define sigma_table_nw(a) (2*weight2(a)) /* <table...> */
89
#else /* not MATRIX */
99
return LOG_MIN * (log((double)x / LOG_MIN) + 1.);
101
#endif /* not MATRIX */
104
bsearch_2short(short e1, short *ent1, short e2, short *ent2, int base,
105
short *indexarray, int nent)
110
int e = e1 * base + e2;
113
int idx = indexarray[k + nn];
114
int ne = ent1[idx] * base + ent2[idx];
131
bsearch_double(double e, double *ent, short *indexarray, int nent)
138
int idx = indexarray[k + nn];
139
double ne = ent[idx];
156
ceil_at_intervals(int x, int step)
167
floor_at_intervals(int x, int step)
177
#define round(x) ((int)floor((x)+0.5))
181
dv2sv(double *dv, short *iv, int size)
188
indexarray = NewAtom_N(short, size);
189
edv = NewAtom_N(double, size);
190
for (i = 0; i < size; i++) {
192
edv[i] = (double)iv[i] - dv[i];
196
for (k = 0; k < size; k++) {
199
i = bsearch_double(x, edv, indexarray, k);
202
for (ii = k; ii > i; ii--)
203
indexarray[ii] = indexarray[ii - 1];
207
iw = min((int)(w + 0.5), size);
210
x = edv[(int)indexarray[iw - 1]];
211
for (i = 0; i < size; i++) {
213
if (i >= iw && abs(edv[k] - x) > 1e-6)
221
table_colspan(struct table *t, int row, int col)
224
for (i = col + 1; i <= t->maxcol && (t->tabattr[row][i] & HTT_X); i++) ;
229
table_rowspan(struct table *t, int row, int col)
232
if (!t->tabattr[row])
234
for (i = row + 1; i <= t->maxrow && t->tabattr[i] &&
235
(t->tabattr[i][col] & HTT_Y); i++) ;
240
minimum_cellspacing(int border_mode)
242
switch (border_mode) {
256
table_border_width(struct table *t)
258
switch (t->border_mode) {
261
return t->maxcol * t->cellspacing + 2 * (RULE_WIDTH + t->cellpadding);
264
return t->maxcol * t->cellspacing;
277
t = New(struct table);
278
t->max_rowsize = MAXROW;
279
t->tabdata = New_N(GeneralList **, MAXROW);
280
t->tabattr = New_N(table_attr *, MAXROW);
281
t->tabheight = NewAtom_N(short, MAXROW);
283
t->tabidvalue = New_N(Str *, MAXROW);
284
t->tridvalue = New_N(Str, MAXROW);
287
for (i = 0; i < MAXROW; i++) {
288
t->tabdata[i] = NULL;
292
t->tabidvalue[i] = NULL;
293
t->tridvalue[i] = NULL;
296
for (j = 0; j < MAXCOL; j++) {
298
t->minimum_width[j] = 0;
299
t->fixed_width[j] = 0;
301
t->cell.maxcell = -1;
311
t->tabcontentssize = 0;
313
t->linfo.prev_ctype = PC_ASCII;
314
t->linfo.prev_spaces = -1;
316
t->linfo.prevchar = Strnew_size(8);
317
set_prevchar(t->linfo.prevchar, "", 0);
320
t->caption = Strnew();
321
t->suspended_data = NULL;
329
check_row(struct table *t, int row)
332
GeneralList ***tabdata;
333
table_attr **tabattr;
340
if (row >= t->max_rowsize) {
341
r = max(t->max_rowsize * 2, row + 1);
342
tabdata = New_N(GeneralList **, r);
343
tabattr = New_N(table_attr *, r);
344
tabheight = NewAtom_N(short, r);
346
tabidvalue = New_N(Str *, r);
347
tridvalue = New_N(Str, r);
349
for (i = 0; i < t->max_rowsize; i++) {
350
tabdata[i] = t->tabdata[i];
351
tabattr[i] = t->tabattr[i];
352
tabheight[i] = t->tabheight[i];
354
tabidvalue[i] = t->tabidvalue[i];
355
tridvalue[i] = t->tridvalue[i];
363
tabidvalue[i] = NULL;
367
t->tabdata = tabdata;
368
t->tabattr = tabattr;
369
t->tabheight = tabheight;
371
t->tabidvalue = tabidvalue;
372
t->tridvalue = tridvalue;
377
if (t->tabdata[row] == NULL) {
378
t->tabdata[row] = New_N(GeneralList *, MAXCOL);
379
t->tabattr[row] = NewAtom_N(table_attr, MAXCOL);
381
t->tabidvalue[row] = New_N(Str, MAXCOL);
383
for (i = 0; i < MAXCOL; i++) {
384
t->tabdata[row][i] = NULL;
385
t->tabattr[row][i] = 0;
387
t->tabidvalue[row][i] = NULL;
394
pushdata(struct table *t, int row, int col, char *data)
397
if (t->tabdata[row][col] == NULL)
398
t->tabdata[row][col] = newGeneralList();
400
pushText(t->tabdata[row][col], data ? data : "");
404
suspend_or_pushdata(struct table *tbl, char *line)
406
if (tbl->flag & TBL_IN_COL)
407
pushdata(tbl, tbl->row, tbl->col, line);
409
if (!tbl->suspended_data)
410
tbl->suspended_data = newTextList();
411
pushText(tbl->suspended_data, line ? line : "");
416
#define PUSH_TAG(str,n) Strcat_charp_n(tagbuf, str, n)
418
#define PUSH_TAG(str,n) Strcat_char(tagbuf, *str)
421
int visible_length_offset = 0;
423
visible_length(char *str)
425
int len = 0, n, max_len = 0;
426
int status = R_ST_NORMAL;
427
int prev_status = status;
428
Str tagbuf = Strnew();
434
prev_status = status;
435
if (next_status(*str, &status)) {
437
len += get_mcwidth(str);
447
if (status == R_ST_TAG0) {
451
else if (status == R_ST_TAG || status == R_ST_DQUOTE
452
|| status == R_ST_QUOTE || status == R_ST_EQL
453
|| status == R_ST_VALUE) {
456
else if (status == R_ST_AMP) {
457
if (prev_status == R_ST_NORMAL) {
467
else if (status == R_ST_NORMAL && prev_status == R_ST_AMP) {
470
t = getescapecmd(&r2);
471
if (!*r2 && (*t == '\r' || *t == '\n')) {
477
len += get_strwidth(t) + get_strwidth(r2);
479
else if (status == R_ST_NORMAL && ST_IS_REAL_TAG(prev_status)) {
482
else if (*str == '\t') {
486
} while ((visible_length_offset + len) % Tabstop != 0);
488
else if (*str == '\r' || *str == '\n') {
500
if (status == R_ST_AMP) {
502
t = getescapecmd(&r2);
503
if (*t != '\r' && *t != '\n')
504
len += get_strwidth(t) + get_strwidth(r2);
506
return len > max_len ? len : max_len;
510
visible_length_plain(char *str)
512
int len = 0, max_len = 0;
518
} while ((visible_length_offset + len) % Tabstop != 0);
521
else if (*str == '\r' || *str == '\n') {
529
len += get_mcwidth(str);
530
str += get_mclen(str);
537
return len > max_len ? len : max_len;
541
maximum_visible_length(char *str, int offset)
543
visible_length_offset = offset;
544
return visible_length(str);
548
maximum_visible_length_plain(char *str, int offset)
550
visible_length_offset = offset;
551
return visible_length_plain(str);
555
align(TextLine *lbuf, int width, int mode)
558
Str buf, line = lbuf->line;
560
if (line->length == 0) {
561
for (i = 0; i < width; i++)
562
Strcat_char(line, ' ');
567
l = width - lbuf->pos;
572
for (i = 0; i < l1; i++)
573
Strcat_char(buf, ' ');
575
for (i = 0; i < l2; i++)
576
Strcat_char(buf, ' ');
580
for (i = 0; i < l; i++)
581
Strcat_char(buf, ' ');
584
for (i = 0; i < l; i++)
585
Strcat_char(buf, ' ');
592
if (lbuf->pos < width)
597
print_item(struct table *t, int row, int col, int width, Str buf)
603
lbuf = popTextLine(t->tabdata[row][col]);
609
alignment = ALIGN_CENTER;
610
if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_LEFT)
611
alignment = ALIGN_LEFT;
612
else if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_RIGHT)
613
alignment = ALIGN_RIGHT;
614
else if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_CENTER)
615
alignment = ALIGN_CENTER;
616
align(lbuf, width, alignment);
617
Strcat(buf, lbuf->line);
620
lbuf = newTextLine(NULL, 0);
621
align(lbuf, width, ALIGN_CENTER);
622
Strcat(buf, lbuf->line);
632
print_sep(struct table *t, int row, int type, int maxcol, Str buf)
640
check_row(t, row + 1);
641
if ((type == T_TOP || type == T_BOTTOM) && t->border_mode == BORDER_THICK) {
642
rule_mode = BORDER_THICK;
645
rule_mode = BORDER_THIN;
650
else if (type == T_BOTTOM)
652
else if (t->tabattr[row + 1][0] & HTT_Y) {
655
if (t->border_mode != BORDER_NOWIN) {
656
push_symbol(buf, RULE(t->border_mode, forbid), symbol_width, 1);
658
for (i = 0; i <= maxcol; i++) {
660
if (type != T_BOTTOM && (t->tabattr[row + 1][i] & HTT_Y)) {
661
if (t->tabattr[row + 1][i] & HTT_X) {
666
k >= 0 && t->tabattr[k] && (t->tabattr[k][i] & HTT_Y);
668
m = t->tabwidth[i] + 2 * t->cellpadding;
669
for (l = i + 1; l <= t->maxcol && (t->tabattr[row][l] & HTT_X);
671
m += t->tabwidth[l] + t->cellspacing;
672
print_item(t, k, i, m, buf);
676
int w = t->tabwidth[i] + 2 * t->cellpadding;
678
w = (w + 1) / RULE_WIDTH;
679
push_symbol(buf, RULE(rule_mode, forbid), symbol_width, w);
686
else if (t->tabattr[row][i + 1] & HTT_X) {
689
if (type == T_BOTTOM)
692
if (t->tabattr[row + 1][i + 1] & HTT_X) {
695
if (t->tabattr[row + 1][i + 1] & HTT_Y) {
698
if (t->tabattr[row + 1][i] & HTT_Y) {
702
if (forbid != 15) /* forbid==15 means 'no rule at all' */
703
push_symbol(buf, RULE(rule_mode, forbid), symbol_width, 1);
709
if (type == T_BOTTOM)
711
if (t->tabattr[row + 1][maxcol] & HTT_Y) {
714
if (t->border_mode != BORDER_NOWIN)
715
push_symbol(buf, RULE(t->border_mode, forbid), symbol_width, 1);
719
get_spec_cell_width(struct table *tbl, int row, int col)
723
w = tbl->tabwidth[col];
724
for (i = col + 1; i <= tbl->maxcol; i++) {
726
if (tbl->tabattr[row][i] & HTT_X)
727
w += tbl->tabwidth[i] + tbl->cellspacing;
735
do_refill(struct table *tbl, int row, int col, int maxlimit)
739
struct readbuffer obuf;
740
struct html_feed_environ h_env;
741
struct environment envs[MAX_ENV_LEVEL];
744
if (tbl->tabdata[row] == NULL || tbl->tabdata[row][col] == NULL)
746
orgdata = (TextList *)tbl->tabdata[row][col];
747
tbl->tabdata[row][col] = newGeneralList();
749
init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL,
750
(TextLineList *)tbl->tabdata[row][col],
751
get_spec_cell_width(tbl, row, col), 0);
752
obuf.flag |= RB_INTABLE;
753
if (h_env.limit > maxlimit)
754
h_env.limit = maxlimit;
755
if (tbl->border_mode != BORDER_NONE && tbl->vcellpadding > 0)
756
do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
757
for (l = orgdata->first; l != NULL; l = l->next) {
758
if (TAG_IS(l->ptr, "<table_alt", 10)) {
761
struct parsed_tag *tag;
762
if ((tag = parse_tag(&p, TRUE)) != NULL)
763
parsedtag_get_value(tag, ATTR_TID, &id);
764
if (id >= 0 && id < tbl->ntable) {
766
TextLineListItem *ti;
767
struct table *t = tbl->tables[id].ptr;
768
int limit = tbl->tables[id].indent + t->total_width;
769
tbl->tables[id].ptr = NULL;
770
save_fonteffect(&h_env, h_env.obuf);
771
flushline(&h_env, &obuf, 0, 2, h_env.limit);
772
if (t->vspace > 0 && !(obuf.flag & RB_IGNORE_P))
773
do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
774
if (RB_GET_ALIGN(h_env.obuf) == RB_CENTER)
775
alignment = ALIGN_CENTER;
776
else if (RB_GET_ALIGN(h_env.obuf) == RB_RIGHT)
777
alignment = ALIGN_RIGHT;
779
alignment = ALIGN_LEFT;
781
if (alignment != ALIGN_LEFT) {
782
for (ti = tbl->tables[id].buf->first;
783
ti != NULL; ti = ti->next)
784
align(ti->ptr, h_env.limit, alignment);
786
appendTextLineList(h_env.buf, tbl->tables[id].buf);
787
if (h_env.maxlimit < limit)
788
h_env.maxlimit = limit;
789
restore_fonteffect(&h_env, h_env.obuf);
790
obuf.flag &= ~RB_IGNORE_P;
791
h_env.blank_lines = 0;
793
do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
794
obuf.flag |= RB_IGNORE_P;
799
HTMLlineproc1(l->ptr, &h_env);
801
if (obuf.status != R_ST_NORMAL) {
802
obuf.status = R_ST_EOL;
803
HTMLlineproc1("\n", &h_env);
805
completeHTMLstream(&h_env, &obuf);
806
flushline(&h_env, &obuf, 0, 2, h_env.limit);
807
if (tbl->border_mode == BORDER_NONE) {
808
int rowspan = table_rowspan(tbl, row, col);
809
if (row + rowspan <= tbl->maxrow) {
810
if (tbl->vcellpadding > 0 && !(obuf.flag & RB_IGNORE_P))
811
do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
819
if (tbl->vcellpadding > 0) {
820
if (!(obuf.flag & RB_IGNORE_P))
821
do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
826
if ((colspan = table_colspan(tbl, row, col)) > 1) {
827
struct table_cell *cell = &tbl->cell;
829
k = bsearch_2short(colspan, cell->colspan, col, cell->col, MAXCOL,
830
cell->index, cell->maxcell + 1);
831
icell = cell->index[k];
832
if (cell->minimum_width[icell] < h_env.maxlimit)
833
cell->minimum_width[icell] = h_env.maxlimit;
836
if (tbl->minimum_width[col] < h_env.maxlimit)
837
tbl->minimum_width[col] = h_env.maxlimit;
842
table_rule_width(struct table *t)
844
if (t->border_mode == BORDER_NONE)
850
check_cell_width(short *tabwidth, short *cellwidth,
851
short *col, short *colspan, short maxcell,
852
short *indexarray, int space, int dir)
854
int i, j, k, bcol, ecol;
857
for (k = 0; k <= maxcell; k++) {
859
if (cellwidth[j] <= 0)
862
ecol = bcol + colspan[j];
864
for (i = bcol; i < ecol; i++)
865
swidth += tabwidth[i];
867
width = cellwidth[j] - (colspan[j] - 1) * space;
868
if (width > swidth) {
869
int w = (width - swidth) / colspan[j];
870
int r = (width - swidth) % colspan[j];
871
for (i = bcol; i < ecol; i++)
873
/* dir {0: horizontal, 1: vertical} */
874
if (dir == 1 && r > 0)
876
for (i = 1; i <= r; i++)
877
tabwidth[ecol - i]++;
883
check_minimum_width(struct table *t, short *tabwidth)
886
struct table_cell *cell = &t->cell;
888
for (i = 0; i <= t->maxcol; i++) {
889
if (tabwidth[i] < t->minimum_width[i])
890
tabwidth[i] = t->minimum_width[i];
893
check_cell_width(tabwidth, cell->minimum_width, cell->col, cell->colspan,
894
cell->maxcell, cell->index, t->cellspacing, 0);
898
check_maximum_width(struct table *t)
900
struct table_cell *cell = &t->cell;
902
int i, j, bcol, ecol;
906
for (j = 0; j <= cell->maxcell; j++) {
908
ecol = bcol + cell->colspan[j];
910
for (i = bcol; i < ecol; i++)
911
swidth += t->tabwidth[i];
913
width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
914
if (width > swidth) {
915
cell->eindex[cell->necell] = j;
919
#else /* not MATRIX */
920
check_cell_width(t->tabwidth, cell->width, cell->col, cell->colspan,
921
cell->maxcell, cell->index, t->cellspacing, 0);
922
check_minimum_width(t, t->tabwidth);
923
#endif /* not MATRIX */
929
set_integered_width(struct table *t, double *dwidth, short *iwidth)
931
int i, j, k, n, bcol, ecol, step;
935
double sum = 0., x = 0.;
936
struct table_cell *cell = &t->cell;
937
int rulewidth = table_rule_width(t);
939
indexarray = NewAtom_N(short, t->maxcol + 1);
940
mod = NewAtom_N(double, t->maxcol + 1);
941
for (i = 0; i <= t->maxcol; i++) {
942
iwidth[i] = ceil_at_intervals(ceil(dwidth[i]), rulewidth);
943
mod[i] = (double)iwidth[i] - dwidth[i];
947
for (k = 0; k <= t->maxcol; k++) {
950
i = bsearch_double(x, mod, indexarray, k);
953
for (ii = k; ii > i; ii--)
954
indexarray[ii] = indexarray[ii - 1];
959
fixed = NewAtom_N(char, t->maxcol + 1);
960
bzero(fixed, t->maxcol + 1);
961
for (step = 0; step < 2; step++) {
962
for (i = 0; i <= t->maxcol; i += n) {
968
for (n = 0; i + n <= t->maxcol; n++) {
969
int ii = indexarray[i + n];
972
else if (fabs(mod[ii] - x) > 1e-6)
975
for (k = 0; k < n; k++) {
976
int ii = indexarray[i + k];
978
iwidth[ii] - rulewidth < t->minimum_width[ii])
981
iwidth[ii] - rulewidth < t->tabwidth[ii] &&
982
(double)rulewidth - mod[ii] > 0.5)
985
idx = NewAtom_N(char, n);
986
for (k = 0; k < cell->maxcell; k++) {
990
ecol = bcol + cell->colspan[j];
992
for (kk = 0; kk < n; kk++) {
993
int ii = indexarray[i + kk];
994
if (ii >= bcol && ii < ecol) {
1001
width = (cell->colspan[j] - 1) * t->cellspacing;
1002
for (kk = bcol; kk < ecol; kk++)
1003
width += iwidth[kk];
1005
for (kk = 0; kk < m; kk++) {
1006
if (fixed[(int)idx[kk]] < 2)
1009
if (width - w < cell->minimum_width[j]) {
1010
for (kk = 0; kk < m; kk++) {
1011
if (fixed[(int)idx[kk]] < 2)
1012
fixed[(int)idx[kk]] = 2;
1016
for (kk = 0; kk < m; kk++) {
1017
if (fixed[(int)idx[kk]] < 1 &&
1018
(double)rulewidth - mod[(int)idx[kk]] > 0.5)
1021
if (width - w < cell->width[j]) {
1022
for (kk = 0; kk < m; kk++) {
1023
if (fixed[(int)idx[kk]] < 1 &&
1024
(double)rulewidth - mod[(int)idx[kk]] > 0.5)
1025
fixed[(int)idx[kk]] = 1;
1030
for (k = 0; k < n; k++) {
1031
int ii = indexarray[i + k];
1032
if (fixed[ii] <= step)
1035
nsum = sum - (double)(nn * rulewidth);
1036
if (nsum < 0. && fabs(sum) <= fabs(nsum))
1038
for (k = 0; k < n; k++) {
1039
int ii = indexarray[i + k];
1040
if (fixed[ii] <= step) {
1041
iwidth[ii] -= rulewidth;
1051
correlation_coefficient(double sxx, double syy, double sxy)
1057
coe = sxy / sqrt(tmp);
1066
correlation_coefficient2(double sxx, double syy, double sxy)
1069
tmp = (syy + sxx - 2 * sxy) * sxx;
1072
coe = (sxx - sxy) / sqrt(tmp);
1081
recalc_width(double old, double swidth, int cwidth,
1082
double sxx, double syy, double sxy, int is_inclusive)
1084
double delta = swidth - (double)cwidth;
1085
double rat = sxy / sxx,
1086
coe = correlation_coefficient(sxx, syy, sxy), w, ww;
1089
if (fabs(coe) < 1e-5)
1094
double wmin = 5e-3 * sqrt(syy * (1. - coe * coe));
1095
if (swidth < 0.2 && cwidth > 0 && is_inclusive) {
1096
double coe1 = correlation_coefficient2(sxx, syy, sxy);
1097
if (coe > 0.9 || coe1 > 0.9)
1107
double wmin = 5e-3 * sqrt(syy) * fabs(coe);
1122
check_compressible_cell(struct table *t, MAT * minv,
1123
double *newwidth, double *swidth, short *cwidth,
1124
double totalwidth, double *Sxx,
1125
int icol, int icell, double sxx, int corr)
1127
struct table_cell *cell = &t->cell;
1128
int i, j, k, m, bcol, ecol, span;
1129
double delta, owidth;
1130
double dmax, dmin, sxy;
1131
int rulewidth = table_rule_width(t);
1137
owidth = newwidth[icol];
1138
delta = newwidth[icol] - (double)t->tabwidth[icol];
1142
else if (icell >= 0) {
1143
owidth = swidth[icell];
1144
delta = swidth[icell] - (double)cwidth[icell];
1145
bcol = cell->col[icell];
1146
ecol = bcol + cell->colspan[icell];
1149
owidth = totalwidth;
1152
ecol = t->maxcol + 1;
1157
for (k = 0; k <= cell->maxcell; k++) {
1159
int is_inclusive = 0;
1165
bcol1 = cell->col[j];
1166
ecol1 = bcol1 + cell->colspan[j];
1168
for (m = bcol1; m < ecol1; m++) {
1169
for (i = bcol; i < ecol; i++)
1170
sxy += m_entry(minv, i, m);
1172
if (bcol1 >= bcol && ecol1 <= ecol) {
1176
dmin = recalc_width(dmin, swidth[j], cwidth[j],
1177
sxx, Sxx[j], sxy, is_inclusive);
1179
dmax = recalc_width(dmax, swidth[j], cwidth[j],
1180
sxx, Sxx[j], sxy, is_inclusive);
1182
for (m = 0; m <= t->maxcol; m++) {
1183
int is_inclusive = 0;
1189
for (i = bcol; i < ecol; i++)
1190
sxy += m_entry(minv, i, m);
1191
if (m >= bcol && m < ecol) {
1195
dmin = recalc_width(dmin, newwidth[m], t->tabwidth[m],
1196
sxx, m_entry(minv, m, m), sxy, is_inclusive);
1198
dmax = recalc_width(dmax, newwidth[m], t->tabwidth[m],
1199
sxx, m_entry(minv, m, m), sxy, is_inclusive);
1202
if (dmax > 0. && dmin > dmax)
1205
if ((span == t->maxcol + 1 && dmin >= 0.) ||
1206
(span != t->maxcol + 1 && dmin > rulewidth * 0.5)) {
1207
int nwidth = ceil_at_intervals(round(owidth - dmin), rulewidth);
1208
correct_table_matrix(t, bcol, ecol - bcol, nwidth, 1.);
1214
#define MAX_ITERATION 10
1216
check_table_width(struct table *t, double *newwidth, MAT * minv, int itr)
1218
int i, j, k, m, bcol, ecol;
1220
struct table_cell *cell = &t->cell;
1222
short orgwidth[t->maxcol + 1], corwidth[t->maxcol + 1];
1223
short cwidth[cell->maxcell + 1];
1224
double swidth[cell->maxcell + 1];
1225
#else /* __GNUC__ */
1226
short orgwidth[MAXCOL], corwidth[MAXCOL];
1227
short cwidth[MAXCELL];
1228
double swidth[MAXCELL];
1229
#endif /* __GNUC__ */
1230
double twidth, sxy, *Sxx, stotal;
1234
for (i = 0; i <= t->maxcol; i++) {
1235
twidth += newwidth[i];
1236
stotal += m_entry(minv, i, i);
1237
for (m = 0; m < i; m++) {
1238
stotal += 2 * m_entry(minv, i, m);
1242
Sxx = NewAtom_N(double, cell->maxcell + 1);
1243
for (k = 0; k <= cell->maxcell; k++) {
1245
bcol = cell->col[j];
1246
ecol = bcol + cell->colspan[j];
1248
for (i = bcol; i < ecol; i++)
1249
swidth[j] += newwidth[i];
1250
cwidth[j] = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
1252
for (i = bcol; i < ecol; i++) {
1253
Sxx[j] += m_entry(minv, i, i);
1254
for (m = bcol; m <= ecol; m++) {
1256
Sxx[j] += 2 * m_entry(minv, i, m);
1261
/* compress table */
1262
corr = check_compressible_cell(t, minv, newwidth, swidth,
1263
cwidth, twidth, Sxx, -1, -1, stotal, corr);
1264
if (itr < MAX_ITERATION && corr > 0)
1267
/* compress multicolumn cell */
1268
for (k = cell->maxcell; k >= 0; k--) {
1270
corr = check_compressible_cell(t, minv, newwidth, swidth,
1271
cwidth, twidth, Sxx,
1272
-1, j, Sxx[j], corr);
1273
if (itr < MAX_ITERATION && corr > 0)
1277
/* compress single column cell */
1278
for (i = 0; i <= t->maxcol; i++) {
1279
corr = check_compressible_cell(t, minv, newwidth, swidth,
1280
cwidth, twidth, Sxx,
1281
i, -1, m_entry(minv, i, i), corr);
1282
if (itr < MAX_ITERATION && corr > 0)
1287
for (i = 0; i <= t->maxcol; i++)
1288
corwidth[i] = orgwidth[i] = round(newwidth[i]);
1290
check_minimum_width(t, corwidth);
1292
for (i = 0; i <= t->maxcol; i++) {
1293
double sx = sqrt(m_entry(minv, i, i));
1296
if (orgwidth[i] < t->minimum_width[i] &&
1297
corwidth[i] == t->minimum_width[i]) {
1298
double w = (sx > 0.5) ? 0.5 : sx * 0.2;
1300
for (m = 0; m <= t->maxcol; m++) {
1303
sxy += m_entry(minv, i, m);
1306
correct_table_matrix(t, i, 1, t->minimum_width[i], w);
1312
for (k = 0; k <= cell->maxcell; k++) {
1313
int nwidth = 0, mwidth;
1320
bcol = cell->col[j];
1321
ecol = bcol + cell->colspan[j];
1322
for (i = bcol; i < ecol; i++)
1323
nwidth += corwidth[i];
1325
cell->minimum_width[j] - (cell->colspan[j] - 1) * t->cellspacing;
1326
if (mwidth > swidth[j] && mwidth == nwidth) {
1327
double w = (sx > 0.5) ? 0.5 : sx * 0.2;
1330
for (i = bcol; i < ecol; i++) {
1331
for (m = 0; m <= t->maxcol; m++) {
1332
if (m >= bcol && m < ecol)
1334
sxy += m_entry(minv, i, m);
1338
correct_table_matrix(t, bcol, cell->colspan[j], mwidth, w);
1344
if (itr >= MAX_ITERATION)
1350
#else /* not MATRIX */
1352
set_table_width(struct table *t, short *newwidth, int maxwidth)
1354
int i, j, k, bcol, ecol;
1355
struct table_cell *cell = &t->cell;
1357
int swidth, fwidth, width, nvar;
1362
fixed = NewAtom_N(char, t->maxcol + 1);
1363
bzero(fixed, t->maxcol + 1);
1364
dwidth = NewAtom_N(double, t->maxcol + 1);
1366
for (i = 0; i <= t->maxcol; i++) {
1368
if (t->fixed_width[i] < 0) {
1369
t->fixed_width[i] = -t->fixed_width[i] * maxwidth / 100;
1371
if (t->fixed_width[i] > 0) {
1372
newwidth[i] = t->fixed_width[i];
1377
if (newwidth[i] < t->minimum_width[i])
1378
newwidth[i] = t->minimum_width[i];
1381
for (k = 0; k <= cell->maxcell; k++) {
1382
j = cell->indexarray[k];
1383
bcol = cell->col[j];
1384
ecol = bcol + cell->colspan[j];
1386
if (cell->fixed_width[j] < 0)
1387
cell->fixed_width[j] = -cell->fixed_width[j] * maxwidth / 100;
1392
for (i = bcol; i < ecol; i++) {
1394
fwidth += newwidth[i];
1397
swidth += newwidth[i];
1401
width = max(cell->fixed_width[j], cell->minimum_width[j])
1402
- (cell->colspan[j] - 1) * t->cellspacing;
1403
if (nvar > 0 && width > fwidth + swidth) {
1405
for (i = bcol; i < ecol; i++) {
1407
s += weight3(t->tabwidth[i]);
1409
for (i = bcol; i < ecol; i++) {
1411
dwidth[i] = (width - fwidth) * weight3(t->tabwidth[i]) / s;
1413
dwidth[i] = (double)newwidth[i];
1415
dv2sv(dwidth, newwidth, cell->colspan[j]);
1416
if (cell->fixed_width[j] > 0) {
1417
for (i = bcol; i < ecol; i++)
1427
for (i = 0; i <= t->maxcol; i++) {
1429
fwidth += newwidth[i];
1432
swidth += newwidth[i];
1436
width = maxwidth - t->maxcol * t->cellspacing;
1437
if (nvar == 0 || width <= fwidth + swidth)
1441
for (i = 0; i <= t->maxcol; i++) {
1443
s += weight3(t->tabwidth[i]);
1445
for (i = 0; i <= t->maxcol; i++) {
1447
dwidth[i] = (width - fwidth) * weight3(t->tabwidth[i]) / s;
1449
dwidth[i] = (double)newwidth[i];
1451
dv2sv(dwidth, newwidth, t->maxcol + 1);
1454
for (i = 0; i <= t->maxcol; i++) {
1456
if (newwidth[i] > t->tabwidth[i]) {
1457
newwidth[i] = t->tabwidth[i];
1461
else if (newwidth[i] < t->minimum_width[i]) {
1462
newwidth[i] = t->minimum_width[i];
1468
} while (try_again);
1470
#endif /* not MATRIX */
1473
check_table_height(struct table *t)
1489
for (j = 0; j <= t->maxrow; j++) {
1492
for (i = 0; i <= t->maxcol; i++) {
1494
if (t->tabattr[j][i] & (HTT_X | HTT_Y))
1497
if (t->tabdata[j][i] == NULL)
1500
t_dep = t->tabdata[j][i]->nitem;
1502
rowspan = table_rowspan(t, j, i);
1504
int c = cell.maxcell + 1;
1505
k = bsearch_2short(rowspan, cell.rowspan,
1506
j, cell.row, t->maxrow + 1, cell.indexarray,
1508
if (k <= cell.maxcell) {
1509
int idx = cell.indexarray[k];
1510
if (cell.row[idx] == j && cell.rowspan[idx] == rowspan)
1513
if (c >= MAXROWCELL)
1515
if (c >= cell.size) {
1516
if (cell.size == 0) {
1517
cell.size = max(MAXCELL, c + 1);
1518
cell.row = NewAtom_N(short, cell.size);
1519
cell.rowspan = NewAtom_N(short, cell.size);
1520
cell.indexarray = NewAtom_N(short, cell.size);
1521
cell.height = NewAtom_N(short, cell.size);
1524
cell.size = max(cell.size + MAXCELL, c + 1);
1525
cell.row = New_Reuse(short, cell.row, cell.size);
1526
cell.rowspan = New_Reuse(short, cell.rowspan,
1528
cell.indexarray = New_Reuse(short, cell.indexarray,
1530
cell.height = New_Reuse(short, cell.height, cell.size);
1533
if (c > cell.maxcell) {
1535
cell.row[cell.maxcell] = j;
1536
cell.rowspan[cell.maxcell] = rowspan;
1537
cell.height[cell.maxcell] = 0;
1538
if (cell.maxcell > k) {
1540
for (ii = cell.maxcell; ii > k; ii--)
1541
cell.indexarray[ii] = cell.indexarray[ii - 1];
1543
cell.indexarray[k] = cell.maxcell;
1546
if (cell.height[c] < t_dep)
1547
cell.height[c] = t_dep;
1550
if (t->tabheight[j] < t_dep)
1551
t->tabheight[j] = t_dep;
1555
switch (t->border_mode) {
1564
check_cell_width(t->tabheight, cell.height, cell.row, cell.rowspan,
1565
cell.maxcell, cell.indexarray, space, 1);
1568
#define CHECK_MINIMUM 1
1569
#define CHECK_FIXED 2
1572
get_table_width(struct table *t, short *orgwidth, short *cellwidth, int flag)
1575
short newwidth[t->maxcol + 1];
1576
#else /* not __GNUC__ */
1577
short newwidth[MAXCOL];
1578
#endif /* not __GNUC__ */
1581
struct table_cell *cell = &t->cell;
1582
int rulewidth = table_rule_width(t);
1584
for (i = 0; i <= t->maxcol; i++)
1585
newwidth[i] = max(orgwidth[i], 0);
1587
if (flag & CHECK_FIXED) {
1589
short ccellwidth[cell->maxcell + 1];
1590
#else /* not __GNUC__ */
1591
short ccellwidth[MAXCELL];
1592
#endif /* not __GNUC__ */
1593
for (i = 0; i <= t->maxcol; i++) {
1594
if (newwidth[i] < t->fixed_width[i])
1595
newwidth[i] = t->fixed_width[i];
1597
for (i = 0; i <= cell->maxcell; i++) {
1598
ccellwidth[i] = cellwidth[i];
1599
if (ccellwidth[i] < cell->fixed_width[i])
1600
ccellwidth[i] = cell->fixed_width[i];
1602
check_cell_width(newwidth, ccellwidth, cell->col, cell->colspan,
1603
cell->maxcell, cell->index, t->cellspacing, 0);
1606
check_cell_width(newwidth, cellwidth, cell->col, cell->colspan,
1607
cell->maxcell, cell->index, t->cellspacing, 0);
1609
if (flag & CHECK_MINIMUM)
1610
check_minimum_width(t, newwidth);
1613
for (i = 0; i <= t->maxcol; i++) {
1614
swidth += ceil_at_intervals(newwidth[i], rulewidth);
1616
swidth += table_border_width(t);
1620
#define minimum_table_width(t)\
1621
(get_table_width(t,t->minimum_width,t->cell.minimum_width,0))
1622
#define maximum_table_width(t)\
1623
(get_table_width(t,t->tabwidth,t->cell.width,CHECK_FIXED))
1624
#define fixed_table_width(t)\
1625
(get_table_width(t,t->fixed_width,t->cell.fixed_width,CHECK_MINIMUM))
1628
renderCoTable(struct table *tbl, int maxlimit)
1630
struct readbuffer obuf;
1631
struct html_feed_environ h_env;
1632
struct environment envs[MAX_ENV_LEVEL];
1635
int indent, maxwidth;
1637
for (i = 0; i < tbl->ntable; i++) {
1638
t = tbl->tables[i].ptr;
1639
col = tbl->tables[i].col;
1640
row = tbl->tables[i].row;
1641
indent = tbl->tables[i].indent;
1643
init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL, tbl->tables[i].buf,
1644
get_spec_cell_width(tbl, row, col), indent);
1645
check_row(tbl, row);
1646
if (h_env.limit > maxlimit)
1647
h_env.limit = maxlimit;
1648
if (t->total_width == 0)
1649
maxwidth = h_env.limit - indent;
1650
else if (t->total_width > 0)
1651
maxwidth = t->total_width;
1653
maxwidth = t->total_width = -t->total_width * h_env.limit / 100;
1654
renderTable(t, maxwidth, &h_env);
1659
make_caption(struct table *t, struct html_feed_environ *h_env)
1661
struct html_feed_environ henv;
1662
struct readbuffer obuf;
1663
struct environment envs[MAX_ENV_LEVEL];
1666
if (t->caption->length <= 0)
1669
if (t->total_width > 0)
1670
limit = t->total_width;
1672
limit = h_env->limit;
1673
init_henv(&henv, &obuf, envs, MAX_ENV_LEVEL, newTextLineList(),
1674
limit, h_env->envs[h_env->envc].indent);
1675
HTMLlineproc1("<center>", &henv);
1676
HTMLlineproc0(t->caption->ptr, &henv, FALSE);
1677
HTMLlineproc1("</center>", &henv);
1679
if (t->total_width < henv.maxlimit)
1680
t->total_width = henv.maxlimit;
1681
limit = h_env->limit;
1682
h_env->limit = t->total_width;
1683
HTMLlineproc1("<center>", h_env);
1684
HTMLlineproc0(t->caption->ptr, h_env, FALSE);
1685
HTMLlineproc1("</center>", h_env);
1686
h_env->limit = limit;
1690
renderTable(struct table *t, int max_width, struct html_feed_environ *h_env)
1694
short new_tabwidth[MAXCOL];
1703
Str vrulea = NULL, vruleb = NULL, vrulec = NULL;
1708
t->total_height = 0;
1709
if (t->maxcol < 0) {
1710
make_caption(t, h_env);
1714
if (t->sloppy_width > max_width)
1715
max_width = t->sloppy_width;
1717
rulewidth = table_rule_width(t);
1719
max_width -= table_border_width(t);
1722
max_width = floor_at_intervals(max_width, rulewidth);
1724
if (max_width < rulewidth)
1725
max_width = rulewidth;
1727
check_maximum_width(t);
1730
if (t->maxcol == 0) {
1731
if (t->tabwidth[0] > max_width)
1732
t->tabwidth[0] = max_width;
1733
if (t->total_width > 0)
1734
t->tabwidth[0] = max_width;
1735
else if (t->fixed_width[0] > 0)
1736
t->tabwidth[0] = t->fixed_width[0];
1737
if (t->tabwidth[0] < t->minimum_width[0])
1738
t->tabwidth[0] = t->minimum_width[0];
1741
set_table_matrix(t, max_width);
1744
mat = m_get(t->maxcol + 1, t->maxcol + 1);
1745
pivot = px_get(t->maxcol + 1);
1746
newwidth = v_get(t->maxcol + 1);
1747
minv = m_get(t->maxcol + 1, t->maxcol + 1);
1749
m_copy(t->matrix, mat);
1750
LUfactor(mat, pivot);
1751
LUsolve(mat, pivot, t->vector, newwidth);
1752
LUinverse(mat, pivot, minv);
1754
set_integered_width(t, newwidth->ve, new_tabwidth);
1755
fprintf(stderr, "itr=%d\n", itr);
1756
fprintf(stderr, "max_width=%d\n", max_width);
1757
fprintf(stderr, "minimum : ");
1758
for (i = 0; i <= t->maxcol; i++)
1759
fprintf(stderr, "%2d ", t->minimum_width[i]);
1760
fprintf(stderr, "\nfixed : ");
1761
for (i = 0; i <= t->maxcol; i++)
1762
fprintf(stderr, "%2d ", t->fixed_width[i]);
1763
fprintf(stderr, "\ndecided : ");
1764
for (i = 0; i <= t->maxcol; i++)
1765
fprintf(stderr, "%2d ", new_tabwidth[i]);
1766
fprintf(stderr, "\n");
1767
#endif /* TABLE_DEBUG */
1770
} while (check_table_width(t, newwidth->ve, minv, itr));
1771
set_integered_width(t, newwidth->ve, new_tabwidth);
1772
check_minimum_width(t, new_tabwidth);
1779
for (i = 0; i <= t->maxcol; i++) {
1780
t->tabwidth[i] = new_tabwidth[i];
1783
#else /* not MATRIX */
1784
set_table_width(t, new_tabwidth, max_width);
1785
for (i = 0; i <= t->maxcol; i++) {
1786
t->tabwidth[i] = new_tabwidth[i];
1788
#endif /* not MATRIX */
1790
check_minimum_width(t, t->tabwidth);
1791
for (i = 0; i <= t->maxcol; i++)
1792
t->tabwidth[i] = ceil_at_intervals(t->tabwidth[i], rulewidth);
1794
renderCoTable(t, h_env->limit);
1796
for (i = 0; i <= t->maxcol; i++) {
1797
for (j = 0; j <= t->maxrow; j++) {
1799
if (t->tabattr[j][i] & HTT_Y)
1801
do_refill(t, j, i, h_env->limit);
1805
check_minimum_width(t, t->tabwidth);
1807
for (i = 0; i <= t->maxcol; i++) {
1808
t->tabwidth[i] = ceil_at_intervals(t->tabwidth[i], rulewidth);
1809
t->total_width += t->tabwidth[i];
1812
t->total_width += table_border_width(t);
1814
check_table_height(t);
1816
for (i = 0; i <= t->maxcol; i++) {
1817
for (j = 0; j <= t->maxrow; j++) {
1820
if ((t->tabattr[j][i] & HTT_Y) ||
1821
(t->tabattr[j][i] & HTT_TOP) || (t->tabdata[j][i] == NULL))
1823
h = t->tabheight[j];
1824
for (k = j + 1; k <= t->maxrow; k++) {
1825
if (!(t->tabattr[k][i] & HTT_Y))
1827
h += t->tabheight[k];
1828
switch (t->border_mode) {
1836
h -= t->tabdata[j][i]->nitem;
1837
if (t->tabattr[j][i] & HTT_MIDDLE)
1841
l = newTextLineList();
1842
for (k = 0; k < h; k++)
1843
pushTextLine(l, newTextLine(NULL, 0));
1844
t->tabdata[j][i] = appendGeneralList((GeneralList *)l,
1850
width = t->total_width;
1852
make_caption(t, h_env);
1854
HTMLlineproc1("<pre for_table>", h_env);
1856
if (t->id != NULL) {
1857
idtag = Sprintf("<_id id=\"%s\">", html_quote((t->id)->ptr));
1858
HTMLlineproc1(idtag->ptr, h_env);
1861
switch (t->border_mode) {
1864
renderbuf = Strnew();
1865
print_sep(t, -1, T_TOP, t->maxcol, renderbuf);
1866
push_render_image(renderbuf, width, t->total_width, h_env);
1867
t->total_height += 1;
1871
switch (t->border_mode) {
1876
push_symbol(vrulea, TK_VERTICALBAR(t->border_mode), symbol_width, 1);
1877
for (i = 0; i < t->cellpadding; i++) {
1878
Strcat_char(vrulea, ' ');
1879
Strcat_char(vruleb, ' ');
1880
Strcat_char(vrulec, ' ');
1882
push_symbol(vrulec, TK_VERTICALBAR(t->border_mode), symbol_width, 1);
1884
push_symbol(vruleb, TK_VERTICALBAR(BORDER_THIN), symbol_width, 1);
1885
for (i = 0; i < t->cellpadding; i++)
1886
Strcat_char(vruleb, ' ');
1889
for (i = 0; i < t->cellspacing; i++)
1890
Strcat_char(vruleb, ' ');
1893
for (r = 0; r <= t->maxrow; r++) {
1894
for (h = 0; h < t->tabheight[r]; h++) {
1895
renderbuf = Strnew();
1896
if (t->border_mode == BORDER_THIN
1897
|| t->border_mode == BORDER_THICK)
1898
Strcat(renderbuf, vrulea);
1900
if (t->tridvalue[r] != NULL && h == 0) {
1901
idtag = Sprintf("<_id id=\"%s\">",
1902
html_quote((t->tridvalue[r])->ptr));
1903
Strcat(renderbuf, idtag);
1906
for (i = 0; i <= t->maxcol; i++) {
1909
if (t->tabidvalue[r][i] != NULL && h == 0) {
1910
idtag = Sprintf("<_id id=\"%s\">",
1911
html_quote((t->tabidvalue[r][i])->ptr));
1912
Strcat(renderbuf, idtag);
1915
if (!(t->tabattr[r][i] & HTT_X)) {
1918
j <= t->maxcol && (t->tabattr[r][j] & HTT_X); j++)
1919
w += t->tabwidth[j] + t->cellspacing;
1920
if (t->tabattr[r][i] & HTT_Y) {
1921
for (j = r - 1; j >= 0 && t->tabattr[j]
1922
&& (t->tabattr[j][i] & HTT_Y); j--) ;
1923
print_item(t, j, i, w, renderbuf);
1926
print_item(t, r, i, w, renderbuf);
1928
if (i < t->maxcol && !(t->tabattr[r][i + 1] & HTT_X))
1929
Strcat(renderbuf, vruleb);
1931
switch (t->border_mode) {
1934
Strcat(renderbuf, vrulec);
1935
t->total_height += 1;
1938
push_render_image(renderbuf, width, t->total_width, h_env);
1940
if (r < t->maxrow && t->border_mode != BORDER_NONE) {
1941
renderbuf = Strnew();
1942
print_sep(t, r, T_MIDDLE, t->maxcol, renderbuf);
1943
push_render_image(renderbuf, width, t->total_width, h_env);
1945
t->total_height += t->tabheight[r];
1947
switch (t->border_mode) {
1950
renderbuf = Strnew();
1951
print_sep(t, t->maxrow, T_BOTTOM, t->maxcol, renderbuf);
1952
push_render_image(renderbuf, width, t->total_width, h_env);
1953
t->total_height += 1;
1956
if (t->total_height == 0) {
1957
renderbuf = Strnew_charp(" ");
1960
push_render_image(renderbuf, 1, t->total_width, h_env);
1962
HTMLlineproc1("</pre>", h_env);
1965
#ifdef TABLE_NO_COMPACT
1966
#define THR_PADDING 2
1968
#define THR_PADDING 4
1972
begin_table(int border, int spacing, int padding, int vspace)
1975
int mincell = minimum_cellspacing(border);
1977
int mincell_pixels = round(mincell * pixel_per_char);
1978
int ppc = round(pixel_per_char);
1981
t->row = t->col = -1;
1984
t->border_mode = border;
1986
if (border == BORDER_NOWIN)
1987
t->flag |= TBL_EXPAND_OK;
1989
rcellspacing = spacing + 2 * padding;
1994
t->cellpadding = padding - (mincell_pixels - 4) / 2;
1997
t->cellpadding = rcellspacing - mincell_pixels;
1999
if (t->cellpadding >= ppc)
2000
t->cellpadding /= ppc;
2001
else if (t->cellpadding > 0)
2010
t->cellspacing = 2 * t->cellpadding + mincell;
2013
t->cellspacing = t->cellpadding + mincell;
2016
if (border == BORDER_NONE) {
2017
if (rcellspacing / 2 + vspace <= 1)
2029
if (border == BORDER_NONE) {
2030
if (rcellspacing <= THR_PADDING)
2031
t->vcellpadding = 0;
2033
t->vcellpadding = 1;
2036
if (padding < 2 * ppc - 2)
2037
t->vcellpadding = 0;
2039
t->vcellpadding = 1;
2046
end_table(struct table *tbl)
2048
struct table_cell *cell = &tbl->cell;
2049
int i, rulewidth = table_rule_width(tbl);
2050
if (rulewidth > 1) {
2051
if (tbl->total_width > 0)
2052
tbl->total_width = ceil_at_intervals(tbl->total_width, rulewidth);
2053
for (i = 0; i <= tbl->maxcol; i++) {
2054
tbl->minimum_width[i] =
2055
ceil_at_intervals(tbl->minimum_width[i], rulewidth);
2056
tbl->tabwidth[i] = ceil_at_intervals(tbl->tabwidth[i], rulewidth);
2057
if (tbl->fixed_width[i] > 0)
2058
tbl->fixed_width[i] =
2059
ceil_at_intervals(tbl->fixed_width[i], rulewidth);
2061
for (i = 0; i <= cell->maxcell; i++) {
2062
cell->minimum_width[i] =
2063
ceil_at_intervals(cell->minimum_width[i], rulewidth);
2064
cell->width[i] = ceil_at_intervals(cell->width[i], rulewidth);
2065
if (cell->fixed_width[i] > 0)
2066
cell->fixed_width[i] =
2067
ceil_at_intervals(cell->fixed_width[i], rulewidth);
2070
tbl->sloppy_width = fixed_table_width(tbl);
2071
if (tbl->total_width > tbl->sloppy_width)
2072
tbl->sloppy_width = tbl->total_width;
2076
check_minimum0(struct table *t, int min)
2079
struct table_cell *cell;
2083
if (t->tabwidth[t->col] < 0)
2085
check_row(t, t->row);
2086
w = table_colspan(t, t->row, t->col);
2093
if (cell->icell >= 0 && cell->minimum_width[cell->icell] < min)
2094
cell->minimum_width[cell->icell] = min;
2097
i <= t->maxcol && (i == t->col || (t->tabattr[t->row][i] & HTT_X));
2099
if (t->minimum_width[i] < ww)
2100
t->minimum_width[i] = ww;
2105
setwidth0(struct table *t, struct table_mode *mode)
2108
int width = t->tabcontentssize;
2109
struct table_cell *cell = &t->cell;
2113
if (t->tabwidth[t->col] < 0)
2115
check_row(t, t->row);
2116
if (t->linfo.prev_spaces > 0)
2117
width -= t->linfo.prev_spaces;
2118
w = table_colspan(t, t->row, t->col);
2120
if (t->tabwidth[t->col] < width)
2121
t->tabwidth[t->col] = width;
2123
else if (cell->icell >= 0) {
2124
if (cell->width[cell->icell] < width)
2125
cell->width[cell->icell] = width;
2131
setwidth(struct table *t, struct table_mode *mode)
2133
int width = setwidth0(t, mode);
2137
if (t->tabattr[t->row][t->col] & HTT_NOWRAP)
2138
check_minimum0(t, width);
2140
if (mode->pre_mode & (TBLM_NOBR | TBLM_PRE | TBLM_PRE_INT) &&
2141
mode->nobr_offset >= 0)
2142
check_minimum0(t, width - mode->nobr_offset);
2146
addcontentssize(struct table *t, int width)
2151
if (t->tabwidth[t->col] < 0)
2153
check_row(t, t->row);
2154
t->tabcontentssize += width;
2157
static void table_close_anchor0(struct table *tbl, struct table_mode *mode);
2160
clearcontentssize(struct table *t, struct table_mode *mode)
2162
table_close_anchor0(t, mode);
2163
mode->nobr_offset = 0;
2164
t->linfo.prev_spaces = -1;
2165
set_space_to_prevchar(t->linfo.prevchar);
2166
t->linfo.prev_ctype = PC_ASCII;
2167
t->linfo.length = 0;
2168
t->tabcontentssize = 0;
2172
begin_cell(struct table *t, struct table_mode *mode)
2174
clearcontentssize(t, mode);
2175
mode->indent_level = 0;
2176
mode->nobr_level = 0;
2179
t->flag |= TBL_IN_COL;
2181
if (t->suspended_data) {
2182
check_row(t, t->row);
2183
if (t->tabdata[t->row][t->col] == NULL)
2184
t->tabdata[t->row][t->col] = newGeneralList();
2185
appendGeneralList(t->tabdata[t->row][t->col],
2186
(GeneralList *)t->suspended_data);
2187
t->suspended_data = NULL;
2192
check_rowcol(struct table *tbl, struct table_mode *mode)
2194
int row = tbl->row, col = tbl->col;
2196
if (!(tbl->flag & TBL_IN_ROW)) {
2197
tbl->flag |= TBL_IN_ROW;
2199
if (tbl->row > tbl->maxrow)
2200
tbl->maxrow = tbl->row;
2208
for (;; tbl->row++) {
2209
check_row(tbl, tbl->row);
2210
for (; tbl->col < MAXCOL &&
2211
tbl->tabattr[tbl->row][tbl->col] & (HTT_X | HTT_Y); tbl->col++) ;
2212
if (tbl->col < MAXCOL)
2216
if (tbl->row > tbl->maxrow)
2217
tbl->maxrow = tbl->row;
2218
if (tbl->col > tbl->maxcol)
2219
tbl->maxcol = tbl->col;
2221
if (tbl->row != row || tbl->col != col)
2222
begin_cell(tbl, mode);
2223
tbl->flag |= TBL_IN_COL;
2227
skip_space(struct table *t, char *line, struct table_linfo *linfo,
2230
int skip = 0, s = linfo->prev_spaces;
2231
Lineprop ctype, prev_ctype = linfo->prev_ctype;
2232
Str prevchar = linfo->prevchar;
2233
int w = linfo->length;
2236
if (*line == '<' && line[strlen(line) - 1] == '>') {
2238
check_minimum0(t, visible_length(line));
2243
char *save = line, *c = line;
2244
int ec, len, wlen, plen;
2245
ctype = get_mctype(line);
2246
len = get_mcwidth(line);
2247
wlen = plen = get_mclen(line);
2251
if (ctype == PC_ASCII && IS_SPACE(*c)) {
2257
ec = getescapechar(&line);
2259
c = conv_entity(ec);
2260
ctype = get_mctype(c);
2261
len = get_strwidth(c);
2263
plen = get_mclen(c);
2266
if (prevchar->length && is_boundary((unsigned char *)prevchar->ptr,
2267
(unsigned char *)c)) {
2275
if (ctype == PC_KANJI1 && prev_ctype == PC_KANJI1)
2284
set_prevchar(prevchar, c, plen);
2289
linfo->prev_spaces = 1;
2292
linfo->prev_spaces = s;
2294
linfo->prev_ctype = prev_ctype;
2295
linfo->prevchar = prevchar;
2301
check_minimum0(t, min);
2307
feed_table_inline_tag(struct table *tbl,
2308
char *line, struct table_mode *mode, int width)
2310
check_rowcol(tbl, mode);
2311
pushdata(tbl, tbl->row, tbl->col, line);
2313
check_minimum0(tbl, width);
2314
addcontentssize(tbl, width);
2315
setwidth(tbl, mode);
2320
feed_table_block_tag(struct table *tbl,
2321
char *line, struct table_mode *mode, int indent, int cmd)
2324
if (mode->indent_level <= 0 && indent == -1)
2326
setwidth(tbl, mode);
2327
feed_table_inline_tag(tbl, line, mode, -1);
2328
clearcontentssize(tbl, mode);
2330
mode->indent_level++;
2331
if (mode->indent_level <= MAX_INDENT_LEVEL)
2332
tbl->indent += INDENT_INCR;
2334
else if (indent == -1) {
2335
mode->indent_level--;
2336
if (mode->indent_level < MAX_INDENT_LEVEL)
2337
tbl->indent -= INDENT_INCR;
2339
offset = tbl->indent;
2340
if (cmd == HTML_DT) {
2341
if (mode->indent_level > 0 && mode->indent_level <= MAX_INDENT_LEVEL)
2342
offset -= INDENT_INCR;
2344
if (tbl->indent > 0) {
2345
check_minimum0(tbl, 0);
2346
addcontentssize(tbl, offset);
2351
table_close_select(struct table *tbl, struct table_mode *mode, int width)
2353
Str tmp = process_n_select();
2354
mode->pre_mode &= ~TBLM_INSELECT;
2356
feed_table1(tbl, tmp, mode, width);
2360
table_close_textarea(struct table *tbl, struct table_mode *mode, int width)
2362
Str tmp = process_n_textarea();
2363
mode->pre_mode &= ~TBLM_INTXTA;
2365
feed_table1(tbl, tmp, mode, width);
2369
table_close_anchor0(struct table *tbl, struct table_mode *mode)
2371
if (!(mode->pre_mode & TBLM_ANCHOR))
2373
mode->pre_mode &= ~TBLM_ANCHOR;
2374
if (tbl->tabcontentssize == mode->anchor_offset) {
2375
check_minimum0(tbl, 1);
2376
addcontentssize(tbl, 1);
2377
setwidth(tbl, mode);
2379
else if (tbl->linfo.prev_spaces > 0 &&
2380
tbl->tabcontentssize - 1 == mode->anchor_offset) {
2381
if (tbl->linfo.prev_spaces > 0)
2382
tbl->linfo.prev_spaces = -1;
2386
#define TAG_ACTION_NONE 0
2387
#define TAG_ACTION_FEED 1
2388
#define TAG_ACTION_TABLE 2
2389
#define TAG_ACTION_N_TABLE 3
2390
#define TAG_ACTION_PLAIN 4
2392
#define CASE_TABLE_TAG \
2407
case HTML_COLGROUP:\
2408
case HTML_N_COLGROUP:\
2411
#define ATTR_ROWSPAN_MAX 32766
2414
feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
2415
int width, struct parsed_tag *tag)
2421
struct table_cell *cell = &tbl->cell;
2422
int colspan, rowspan;
2424
int i, j, k, v, v0, w, id;
2425
Str tok, tmp, anchor;
2426
table_attr align, valign;
2430
if (mode->pre_mode & TBLM_PLAIN) {
2431
if (mode->end_tag == cmd) {
2432
mode->pre_mode &= ~TBLM_PLAIN;
2434
feed_table_block_tag(tbl, line, mode, 0, cmd);
2435
return TAG_ACTION_NONE;
2437
return TAG_ACTION_PLAIN;
2439
if (mode->pre_mode & TBLM_INTXTA) {
2442
case HTML_N_TEXTAREA:
2443
table_close_textarea(tbl, mode, width);
2444
if (cmd == HTML_N_TEXTAREA)
2445
return TAG_ACTION_NONE;
2448
return TAG_ACTION_FEED;
2451
if (mode->pre_mode & TBLM_SCRIPT) {
2452
if (mode->end_tag == cmd) {
2453
mode->pre_mode &= ~TBLM_SCRIPT;
2455
return TAG_ACTION_NONE;
2457
return TAG_ACTION_PLAIN;
2459
if (mode->pre_mode & TBLM_STYLE) {
2460
if (mode->end_tag == cmd) {
2461
mode->pre_mode &= ~TBLM_STYLE;
2463
return TAG_ACTION_NONE;
2465
return TAG_ACTION_PLAIN;
2467
/* failsafe: a tag other than <option></option>and </select> in *
2468
* <select> environment is regarded as the end of <select>. */
2469
if (mode->pre_mode & TBLM_INSELECT) {
2473
case HTML_N_SELECT: /* mode->end_tag */
2474
table_close_select(tbl, mode, width);
2475
if (cmd == HTML_N_SELECT)
2476
return TAG_ACTION_NONE;
2479
return TAG_ACTION_FEED;
2482
if (mode->caption) {
2485
case HTML_N_CAPTION:
2487
if (cmd == HTML_N_CAPTION)
2488
return TAG_ACTION_NONE;
2491
return TAG_ACTION_FEED;
2495
if (mode->pre_mode & TBLM_PRE) {
2500
case HTML_N_PRE_INT:
2501
return TAG_ACTION_NONE;
2507
check_rowcol(tbl, mode);
2508
return TAG_ACTION_TABLE;
2510
if (tbl->suspended_data)
2511
check_rowcol(tbl, mode);
2512
return TAG_ACTION_N_TABLE;
2514
if (tbl->col >= 0 && tbl->tabcontentssize > 0)
2515
setwidth(tbl, mode);
2518
tbl->flag |= TBL_IN_ROW;
2519
tbl->flag &= ~TBL_IN_COL;
2522
if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
2525
align = (HTT_LEFT | HTT_TRSET);
2528
align = (HTT_RIGHT | HTT_TRSET);
2531
align = (HTT_CENTER | HTT_TRSET);
2535
if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
2538
valign = (HTT_TOP | HTT_VTRSET);
2541
valign = (HTT_MIDDLE | HTT_VTRSET);
2544
valign = (HTT_BOTTOM | HTT_VTRSET);
2549
if (parsedtag_get_value(tag, ATTR_ID, &p))
2550
tbl->tridvalue[tbl->row] = Strnew_charp(p);
2552
tbl->trattr = align | valign;
2556
prev_col = tbl->col;
2557
if (tbl->col >= 0 && tbl->tabcontentssize > 0)
2558
setwidth(tbl, mode);
2559
if (tbl->row == -1) {
2560
/* for broken HTML... */
2563
tbl->maxrow = tbl->row;
2565
if (tbl->col == -1) {
2566
if (!(tbl->flag & TBL_IN_ROW)) {
2568
tbl->flag |= TBL_IN_ROW;
2570
if (tbl->row > tbl->maxrow)
2571
tbl->maxrow = tbl->row;
2574
check_row(tbl, tbl->row);
2575
while (tbl->tabattr[tbl->row][tbl->col]) {
2578
if (tbl->col > MAXCOL - 1) {
2579
tbl->col = prev_col;
2580
return TAG_ACTION_NONE;
2582
if (tbl->col > tbl->maxcol) {
2583
tbl->maxcol = tbl->col;
2585
colspan = rowspan = 1;
2586
if (tbl->trattr & HTT_TRSET)
2587
align = (tbl->trattr & HTT_ALIGN);
2588
else if (cmd == HTML_TH)
2592
if (tbl->trattr & HTT_VTRSET)
2593
valign = (tbl->trattr & HTT_VALIGN);
2595
valign = HTT_MIDDLE;
2596
if (parsedtag_get_value(tag, ATTR_ROWSPAN, &rowspan)) {
2597
if(rowspan > ATTR_ROWSPAN_MAX) {
2598
rowspan = ATTR_ROWSPAN_MAX;
2600
if ((tbl->row + rowspan) >= tbl->max_rowsize)
2601
check_row(tbl, tbl->row + rowspan);
2603
if (parsedtag_get_value(tag, ATTR_COLSPAN, &colspan)) {
2604
if ((tbl->col + colspan) >= MAXCOL) {
2605
/* Can't expand column */
2606
colspan = MAXCOL - tbl->col;
2609
if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
2622
if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
2628
valign = HTT_MIDDLE;
2631
valign = HTT_BOTTOM;
2636
if (parsedtag_exists(tag, ATTR_NOWRAP))
2637
tbl->tabattr[tbl->row][tbl->col] |= HTT_NOWRAP;
2640
if (parsedtag_get_value(tag, ATTR_WIDTH, &v)) {
2643
if (tbl->real_width > 0)
2644
v = -(v * 100) / (tbl->real_width * pixel_per_char);
2646
v = (int)(v / pixel_per_char);
2649
v = RELATIVE_WIDTH(v);
2650
#endif /* not TABLE_EXPAND */
2653
if (parsedtag_get_value(tag, ATTR_ID, &p))
2654
tbl->tabidvalue[tbl->row][tbl->col] = Strnew_charp(p);
2658
/* NOWRAP and WIDTH= conflicts each other */
2659
tbl->tabattr[tbl->row][tbl->col] &= ~HTT_NOWRAP;
2662
tbl->tabattr[tbl->row][tbl->col] &= ~(HTT_ALIGN | HTT_VALIGN);
2663
tbl->tabattr[tbl->row][tbl->col] |= (align | valign);
2667
cell->icell = cell->maxcell + 1;
2668
k = bsearch_2short(colspan, cell->colspan, col, cell->col, MAXCOL,
2669
cell->index, cell->icell);
2670
if (k <= cell->maxcell) {
2672
if (cell->col[i] == col && cell->colspan[i] == colspan)
2675
if (cell->icell > cell->maxcell && cell->icell < MAXCELL) {
2677
cell->col[cell->maxcell] = col;
2678
cell->colspan[cell->maxcell] = colspan;
2679
cell->width[cell->maxcell] = 0;
2680
cell->minimum_width[cell->maxcell] = 0;
2681
cell->fixed_width[cell->maxcell] = 0;
2682
if (cell->maxcell > k) {
2684
for (ii = cell->maxcell; ii > k; ii--)
2685
cell->index[ii] = cell->index[ii - 1];
2687
cell->index[k] = cell->maxcell;
2689
if (cell->icell > cell->maxcell)
2694
v0 = tbl->fixed_width[tbl->col];
2695
if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0)) {
2696
#ifdef FEED_TABLE_DEBUG
2697
fprintf(stderr, "width(%d) = %d\n", tbl->col, v);
2698
#endif /* TABLE_DEBUG */
2699
tbl->fixed_width[tbl->col] = v;
2702
else if (cell->icell >= 0) {
2703
v0 = cell->fixed_width[cell->icell];
2704
if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0))
2705
cell->fixed_width[cell->icell] = v;
2708
for (i = 0; i < rowspan; i++) {
2709
check_row(tbl, tbl->row + i);
2710
for (j = 0; j < colspan; j++) {
2712
tbl->tabattr[tbl->row + i][tbl->col + j] &= ~(HTT_X | HTT_Y);
2714
if (!(tbl->tabattr[tbl->row + i][tbl->col + j] &
2716
tbl->tabattr[tbl->row + i][tbl->col + j] |=
2717
((i > 0) ? HTT_Y : 0) | ((j > 0) ? HTT_X : 0);
2719
if (tbl->col + j > tbl->maxcol) {
2720
tbl->maxcol = tbl->col + j;
2723
if (tbl->row + i > tbl->maxrow) {
2724
tbl->maxrow = tbl->row + i;
2727
begin_cell(tbl, mode);
2730
setwidth(tbl, mode);
2732
tbl->flag &= ~(TBL_IN_ROW | TBL_IN_COL);
2733
return TAG_ACTION_NONE;
2736
setwidth(tbl, mode);
2737
tbl->flag &= ~TBL_IN_COL;
2738
#ifdef FEED_TABLE_DEBUG
2741
int i = tbl->col, j = tbl->row;
2742
fprintf(stderr, "(a) row,col: %d, %d\n", j, i);
2743
if (tbl->tabdata[j] && tbl->tabdata[j][i]) {
2744
for (it = ((TextList *)tbl->tabdata[j][i])->first;
2746
fprintf(stderr, " [%s] \n", it->ptr);
2750
return TAG_ACTION_NONE;
2757
if (!(tbl->flag & TBL_IN_ROW))
2769
case HTML_PLAINTEXT:
2770
case HTML_PRE_PLAIN:
2771
case HTML_N_PRE_PLAIN:
2772
feed_table_block_tag(tbl, line, mode, 0, cmd);
2775
case HTML_PRE_PLAIN:
2776
mode->pre_mode |= TBLM_PRE;
2779
case HTML_N_PRE_PLAIN:
2780
mode->pre_mode &= ~TBLM_PRE;
2783
mode->pre_mode |= TBLM_PLAIN;
2784
mode->end_tag = HTML_N_LISTING;
2787
mode->pre_mode |= TBLM_PLAIN;
2788
mode->end_tag = HTML_N_XMP;
2790
case HTML_PLAINTEXT:
2791
mode->pre_mode |= TBLM_PLAIN;
2792
mode->end_tag = MAX_HTMLTAG;
2800
feed_table_block_tag(tbl, line, mode, 1, cmd);
2806
feed_table_block_tag(tbl, line, mode, -1, cmd);
2810
if (!(tbl->flag & TBL_IN_ROW))
2813
feed_table_inline_tag(tbl, line, mode, -1);
2817
if (mode->pre_mode & TBLM_NOBR)
2818
return TAG_ACTION_NONE;
2819
mode->pre_mode |= TBLM_NOBR;
2822
if (mode->pre_mode & TBLM_PRE_INT)
2823
return TAG_ACTION_NONE;
2824
mode->pre_mode |= TBLM_PRE_INT;
2825
tbl->linfo.prev_spaces = 0;
2828
mode->nobr_offset = -1;
2829
if (tbl->linfo.length > 0) {
2830
check_minimum0(tbl, tbl->linfo.length);
2831
tbl->linfo.length = 0;
2835
if (!(tbl->flag & TBL_IN_ROW))
2837
feed_table_inline_tag(tbl, line, mode, -1);
2838
if (mode->nobr_level > 0)
2840
if (mode->nobr_level == 0)
2841
mode->pre_mode &= ~TBLM_NOBR;
2843
case HTML_N_PRE_INT:
2844
feed_table_inline_tag(tbl, line, mode, -1);
2845
mode->pre_mode &= ~TBLM_PRE_INT;
2848
check_rowcol(tbl, mode);
2849
w = tbl->fixed_width[tbl->col];
2851
if (tbl->total_width > 0)
2852
w = -tbl->total_width * w / 100;
2854
w = -width * w / 100;
2859
if (tbl->total_width > 0)
2860
w = tbl->total_width;
2864
tok = process_img(tag, w);
2865
feed_table1(tbl, tok, mode, width);
2868
feed_table_block_tag(tbl, "", mode, 0, cmd);
2869
tmp = process_form(tag);
2871
feed_table1(tbl, tmp, mode, width);
2874
feed_table_block_tag(tbl, "", mode, 0, cmd);
2878
tmp = process_input(tag);
2879
feed_table1(tbl, tmp, mode, width);
2882
tmp = process_select(tag);
2884
feed_table1(tbl, tmp, mode, width);
2885
mode->pre_mode |= TBLM_INSELECT;
2886
mode->end_tag = HTML_N_SELECT;
2894
check_rowcol(tbl, mode);
2895
if (tbl->col + 1 <= tbl->maxcol &&
2896
tbl->tabattr[tbl->row][tbl->col + 1] & HTT_X) {
2897
if (cell->icell >= 0 && cell->fixed_width[cell->icell] > 0)
2898
w = cell->fixed_width[cell->icell];
2901
if (tbl->fixed_width[tbl->col] > 0)
2902
w = tbl->fixed_width[tbl->col];
2904
tmp = process_textarea(tag, w);
2906
feed_table1(tbl, tmp, mode, width);
2907
mode->pre_mode |= TBLM_INTXTA;
2908
mode->end_tag = HTML_N_TEXTAREA;
2911
table_close_anchor0(tbl, mode);
2914
parsedtag_get_value(tag, ATTR_HREF, &anchor);
2915
parsedtag_get_value(tag, ATTR_HSEQ, &i);
2917
check_rowcol(tbl, mode);
2919
Str tmp = process_anchor(tag, line);
2920
if (displayLinkNumber)
2922
Str t = getLinkNumberStr(-1);
2923
feed_table_inline_tag(tbl, NULL, mode, t->length);
2926
pushdata(tbl, tbl->row, tbl->col, tmp->ptr);
2929
pushdata(tbl, tbl->row, tbl->col, line);
2931
mode->pre_mode |= TBLM_ANCHOR;
2932
mode->anchor_offset = tbl->tabcontentssize;
2936
suspend_or_pushdata(tbl, line);
2939
switch (displayInsDel) {
2940
case DISPLAY_INS_DEL_SIMPLE:
2941
mode->pre_mode |= TBLM_DEL;
2943
case DISPLAY_INS_DEL_NORMAL:
2944
feed_table_inline_tag(tbl, line, mode, 5); /* [DEL: */
2946
case DISPLAY_INS_DEL_FONTIFY:
2947
feed_table_inline_tag(tbl, line, mode, -1);
2952
switch (displayInsDel) {
2953
case DISPLAY_INS_DEL_SIMPLE:
2954
mode->pre_mode &= ~TBLM_DEL;
2956
case DISPLAY_INS_DEL_NORMAL:
2957
feed_table_inline_tag(tbl, line, mode, 5); /* :DEL] */
2959
case DISPLAY_INS_DEL_FONTIFY:
2960
feed_table_inline_tag(tbl, line, mode, -1);
2965
switch (displayInsDel) {
2966
case DISPLAY_INS_DEL_SIMPLE:
2967
mode->pre_mode |= TBLM_S;
2969
case DISPLAY_INS_DEL_NORMAL:
2970
feed_table_inline_tag(tbl, line, mode, 3); /* [S: */
2972
case DISPLAY_INS_DEL_FONTIFY:
2973
feed_table_inline_tag(tbl, line, mode, -1);
2978
switch (displayInsDel) {
2979
case DISPLAY_INS_DEL_SIMPLE:
2980
mode->pre_mode &= ~TBLM_S;
2982
case DISPLAY_INS_DEL_NORMAL:
2983
feed_table_inline_tag(tbl, line, mode, 3); /* :S] */
2985
case DISPLAY_INS_DEL_FONTIFY:
2986
feed_table_inline_tag(tbl, line, mode, -1);
2992
switch (displayInsDel) {
2993
case DISPLAY_INS_DEL_SIMPLE:
2995
case DISPLAY_INS_DEL_NORMAL:
2996
feed_table_inline_tag(tbl, line, mode, 5); /* [INS:, :INS] */
2998
case DISPLAY_INS_DEL_FONTIFY:
2999
feed_table_inline_tag(tbl, line, mode, -1);
3006
if (!(mode->pre_mode & (TBLM_DEL | TBLM_S)))
3007
feed_table_inline_tag(tbl, line, mode, 1); /* ^, [, ] */
3011
case HTML_TABLE_ALT:
3014
parsedtag_get_value(tag, ATTR_TID, &id);
3015
if (id >= 0 && id < tbl->ntable) {
3016
struct table *tbl1 = tbl->tables[id].ptr;
3017
feed_table_block_tag(tbl, line, mode, 0, cmd);
3018
addcontentssize(tbl, maximum_table_width(tbl1));
3019
check_minimum0(tbl, tbl1->sloppy_width);
3021
w = tbl1->total_width;
3023
colspan = table_colspan(tbl, tbl->row, tbl->col);
3025
if (cell->icell >= 0)
3026
v = cell->fixed_width[cell->icell];
3029
v = tbl->fixed_width[tbl->col];
3030
if (v < 0 && tbl->real_width > 0 && tbl1->real_width > 0)
3031
w = -(tbl1->real_width * 100) / tbl->real_width;
3033
w = tbl1->real_width;
3035
check_minimum0(tbl, w);
3036
else if (w < 0 && v < w) {
3038
if (cell->icell >= 0)
3039
cell->fixed_width[cell->icell] = w;
3042
tbl->fixed_width[tbl->col] = w;
3045
setwidth0(tbl, mode);
3046
clearcontentssize(tbl, mode);
3052
case HTML_N_CAPTION:
3060
case HTML_N_COLGROUP:
3064
mode->pre_mode |= TBLM_SCRIPT;
3065
mode->end_tag = HTML_N_SCRIPT;
3068
mode->pre_mode |= TBLM_STYLE;
3069
mode->end_tag = HTML_N_STYLE;
3072
table_close_anchor0(tbl, mode);
3076
suspend_or_pushdata(tbl, line);
3079
case HTML_N_INTERNAL:
3081
case HTML_N_FORM_INT:
3082
case HTML_INPUT_ALT:
3083
case HTML_N_INPUT_ALT:
3084
case HTML_SELECT_INT:
3085
case HTML_N_SELECT_INT:
3086
case HTML_OPTION_INT:
3087
case HTML_TEXTAREA_INT:
3088
case HTML_N_TEXTAREA_INT:
3093
/* unknown tag: put into table */
3094
return TAG_ACTION_FEED;
3096
return TAG_ACTION_NONE;
3101
feed_table(struct table *tbl, char *line, struct table_mode *mode,
3102
int width, int internal)
3107
struct table_linfo *linfo = &tbl->linfo;
3109
if (*line == '<' && line[1] && REALLY_THE_BEGINNING_OF_A_TAG(line)) {
3110
struct parsed_tag *tag;
3112
tag = parse_tag(&p, internal);
3114
switch (feed_table_tag(tbl, line, mode, width, tag)) {
3115
case TAG_ACTION_NONE:
3117
case TAG_ACTION_N_TABLE:
3119
case TAG_ACTION_TABLE:
3121
case TAG_ACTION_PLAIN:
3123
case TAG_ACTION_FEED:
3125
if (parsedtag_need_reconstruct(tag))
3126
line = parsedtag2str(tag)->ptr;
3130
if (!(mode->pre_mode & (TBLM_PLAIN | TBLM_INTXTA | TBLM_INSELECT |
3131
TBLM_SCRIPT | TBLM_STYLE)))
3136
if (mode->pre_mode & (TBLM_DEL | TBLM_S))
3139
if (mode->caption) {
3140
Strcat_charp(tbl->caption, line);
3143
if (mode->pre_mode & TBLM_SCRIPT)
3145
if (mode->pre_mode & TBLM_STYLE)
3147
if (mode->pre_mode & TBLM_INTXTA) {
3148
feed_textarea(line);
3151
if (mode->pre_mode & TBLM_INSELECT) {
3155
if (!(mode->pre_mode & TBLM_PLAIN) &&
3156
!(*line == '<' && line[strlen(line) - 1] == '>') &&
3157
strchr(line, '&') != NULL) {
3159
for (p = line; *p;) {
3162
if (!strncasecmp(p, "&", 5) ||
3163
!strncasecmp(p, ">", 4) || !strncasecmp(p, "<", 4)) {
3164
/* do not convert */
3165
Strcat_char(tmp, *p);
3171
switch (ec = getescapechar(&p)) {
3173
Strcat_charp(tmp, "<");
3176
Strcat_charp(tmp, ">");
3179
Strcat_charp(tmp, "&");
3182
Strcat_char(tmp, '\n');
3185
r = conv_entity(ec);
3186
if (r != NULL && strlen(r) == 1 &&
3187
ec == (unsigned char)*r) {
3188
Strcat_char(tmp, *r);
3192
Strcat_char(tmp, *q);
3199
Strcat_char(tmp, *p);
3205
if (!(mode->pre_mode & (TBLM_SPECIAL & ~TBLM_NOBR))) {
3206
if (!(tbl->flag & TBL_IN_COL) || linfo->prev_spaces != 0)
3207
while (IS_SPACE(*line))
3211
check_rowcol(tbl, mode);
3212
if (mode->pre_mode & TBLM_NOBR && mode->nobr_offset < 0)
3213
mode->nobr_offset = tbl->tabcontentssize;
3215
/* count of number of spaces skipped in normal mode */
3216
i = skip_space(tbl, line, linfo, !(mode->pre_mode & TBLM_NOBR));
3217
addcontentssize(tbl, visible_length(line) - i);
3218
setwidth(tbl, mode);
3219
pushdata(tbl, tbl->row, tbl->col, line);
3221
else if (mode->pre_mode & TBLM_PRE_INT) {
3222
check_rowcol(tbl, mode);
3223
if (mode->nobr_offset < 0)
3224
mode->nobr_offset = tbl->tabcontentssize;
3225
addcontentssize(tbl, maximum_visible_length(line, tbl->tabcontentssize));
3226
setwidth(tbl, mode);
3227
pushdata(tbl, tbl->row, tbl->col, line);
3230
/* <pre> mode or something like it */
3231
check_rowcol(tbl, mode);
3234
if ((p = strchr(line, '\r')) || (p = strchr(line, '\n'))) {
3235
if (*p == '\r' && p[1] == '\n')
3239
tmp = Strnew_charp_n(line, p - line);
3253
if (mode->pre_mode & TBLM_PLAIN)
3254
i = maximum_visible_length_plain(p, tbl->tabcontentssize);
3256
i = maximum_visible_length(p, tbl->tabcontentssize);
3257
addcontentssize(tbl, i);
3258
setwidth(tbl, mode);
3260
clearcontentssize(tbl, mode);
3261
pushdata(tbl, tbl->row, tbl->col, p);
3268
feed_table1(struct table *tbl, Str tok, struct table_mode *mode, int width)
3276
status = R_ST_NORMAL;
3279
(tokbuf, &line, &status, mode->pre_mode & TBLM_PREMODE, 0))
3280
feed_table(tbl, tokbuf->ptr, mode, width, TRUE);
3284
pushTable(struct table *tbl, struct table *tbl1)
3292
if (tbl->ntable >= tbl->tables_size) {
3293
struct table_in *tmp;
3294
tbl->tables_size += MAX_TABLE_N;
3295
tmp = New_N(struct table_in, tbl->tables_size);
3297
bcopy(tbl->tables, tmp, tbl->ntable * sizeof(struct table_in));
3301
tbl->tables[tbl->ntable].ptr = tbl1;
3302
tbl->tables[tbl->ntable].col = col;
3303
tbl->tables[tbl->ntable].row = row;
3304
tbl->tables[tbl->ntable].indent = tbl->indent;
3305
tbl->tables[tbl->ntable].buf = newTextLineList();
3306
check_row(tbl, row);
3307
if (col + 1 <= tbl->maxcol && tbl->tabattr[row][col + 1] & HTT_X)
3308
tbl->tables[tbl->ntable].cell = tbl->cell.icell;
3310
tbl->tables[tbl->ntable].cell = -1;
3316
correct_table_matrix(struct table *t, int col, int cspan, int a, double b)
3319
int ecol = col + cspan;
3320
double w = 1. / (b * b);
3322
for (i = col; i < ecol; i++) {
3323
v_add_val(t->vector, i, w * a);
3324
for (j = i; j < ecol; j++) {
3325
m_add_val(t->matrix, i, j, w);
3326
m_set_val(t->matrix, j, i, m_entry(t->matrix, i, j));
3333
correct_table_matrix2(struct table *t, int col, int cspan, double s, double b)
3336
int ecol = col + cspan;
3337
int size = t->maxcol + 1;
3338
double w = 1. / (b * b);
3341
for (i = 0; i < size; i++) {
3342
for (j = i; j < size; j++) {
3343
if (i >= col && i < ecol && j >= col && j < ecol)
3344
ss = (1. - s) * (1. - s);
3345
else if ((i >= col && i < ecol) || (j >= col && j < ecol))
3349
m_add_val(t->matrix, i, j, w * ss);
3355
correct_table_matrix3(struct table *t, int col, char *flags, double s,
3360
int size = t->maxcol + 1;
3361
double w = 1. / (b * b);
3362
int flg = (flags[col] == 0);
3364
for (i = 0; i < size; i++) {
3365
if (!((flg && flags[i] == 0) || (!flg && flags[i] != 0)))
3367
for (j = i; j < size; j++) {
3368
if (!((flg && flags[j] == 0) || (!flg && flags[j] != 0)))
3370
if (i == col && j == col)
3371
ss = (1. - s) * (1. - s);
3372
else if (i == col || j == col)
3376
m_add_val(t->matrix, i, j, w * ss);
3382
correct_table_matrix4(struct table *t, int col, int cspan, char *flags,
3387
int ecol = col + cspan;
3388
int size = t->maxcol + 1;
3389
double w = 1. / (b * b);
3391
for (i = 0; i < size; i++) {
3392
if (flags[i] && !(i >= col && i < ecol))
3394
for (j = i; j < size; j++) {
3395
if (flags[j] && !(j >= col && j < ecol))
3397
if (i >= col && i < ecol && j >= col && j < ecol)
3398
ss = (1. - s) * (1. - s);
3399
else if ((i >= col && i < ecol) || (j >= col && j < ecol))
3403
m_add_val(t->matrix, i, j, w * ss);
3409
set_table_matrix0(struct table *t, int maxwidth)
3411
int size = t->maxcol + 1;
3412
int i, j, k, bcol, ecol;
3414
double w0, w1, w, s, b;
3418
#else /* not __GNUC__ */
3420
char expand[MAXCOL];
3421
#endif /* not __GNUC__ */
3422
struct table_cell *cell = &t->cell;
3425
for (i = 0; i < size; i++) {
3426
we[i] = weight(t->tabwidth[i]);
3432
if (cell->necell == 0) {
3433
for (i = 0; i < size; i++) {
3435
b = sigma_td_nw((int)(s * maxwidth));
3436
correct_table_matrix2(t, i, 1, s, b);
3441
bzero(expand, size);
3443
for (k = 0; k < cell->necell; k++) {
3444
j = cell->eindex[k];
3445
bcol = cell->col[j];
3446
ecol = bcol + cell->colspan[j];
3447
width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
3449
for (i = bcol; i < ecol; i++) {
3450
w1 += t->tabwidth[i] + 0.1;
3453
for (i = bcol; i < ecol; i++) {
3454
w = weight(width * (t->tabwidth[i] + 0.1) / w1);
3462
for (i = 0; i < size; i++) {
3470
for (k = 0; k < cell->necell; k++) {
3471
j = cell->eindex[k];
3472
bcol = cell->col[j];
3473
width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
3476
b = sigma_td_nw((int)(s * maxwidth));
3477
correct_table_matrix4(t, bcol, cell->colspan[j], expand, s, b);
3480
for (i = 0; i < size; i++) {
3481
if (expand[i] == 0) {
3482
s = we[i] / max(w1, 1.);
3483
b = sigma_td_nw((int)(s * maxwidth));
3486
s = we[i] / max(w0 - w1, 1.);
3487
b = sigma_td_nw(maxwidth);
3489
correct_table_matrix3(t, i, expand, s, b);
3494
check_relative_width(struct table *t, int maxwidth)
3497
double rel_total = 0;
3498
int size = t->maxcol + 1;
3499
double *rcolwidth = New_N(double, size);
3500
struct table_cell *cell = &t->cell;
3503
for (i = 0; i < size; i++)
3506
for (i = 0; i < size; i++) {
3507
if (t->fixed_width[i] < 0)
3508
rcolwidth[i] = -(double)t->fixed_width[i] / 100.0;
3509
else if (t->fixed_width[i] > 0)
3510
rcolwidth[i] = (double)t->fixed_width[i] / maxwidth;
3514
for (i = 0; i <= cell->maxcell; i++) {
3515
if (cell->fixed_width[i] < 0) {
3516
double w = -(double)cell->fixed_width[i] / 100.0;
3522
for (j = 0; j < cell->colspan[i]; j++) {
3523
if (rcolwidth[j + k] > 0)
3524
r += rcolwidth[j + k];
3528
if (n_leftcell == 0) {
3529
/* w must be identical to r */
3531
cell->fixed_width[i] = -100 * r;
3535
/* make room for the left(width-unspecified) cell */
3536
/* the next formula is an estimation of required width */
3537
w = r * cell->colspan[i] / (cell->colspan[i] - n_leftcell);
3538
cell->fixed_width[i] = -100 * w;
3540
for (j = 0; j < cell->colspan[i]; j++) {
3541
if (rcolwidth[j + k] == 0)
3542
rcolwidth[j + k] = (w - r) / n_leftcell;
3546
else if (cell->fixed_width[i] > 0) {
3551
for (i = 0; i < size; i++)
3552
rel_total += rcolwidth[i];
3554
if ((n_leftcol == 0 && rel_total < 0.9) || 1.1 < rel_total) {
3555
for (i = 0; i < size; i++) {
3556
rcolwidth[i] /= rel_total;
3558
for (i = 0; i < size; i++) {
3559
if (t->fixed_width[i] < 0)
3560
t->fixed_width[i] = -rcolwidth[i] * 100;
3562
for (i = 0; i <= cell->maxcell; i++) {
3563
if (cell->fixed_width[i] < 0) {
3568
for (j = 0; j < cell->colspan[i]; j++)
3569
r += rcolwidth[j + k];
3570
cell->fixed_width[i] = -r * 100;
3577
set_table_matrix(struct table *t, int width)
3579
int size = t->maxcol + 1;
3583
struct table_cell *cell = &t->cell;
3588
t->matrix = m_get(size, size);
3589
t->vector = v_get(size);
3590
for (i = 0; i < size; i++) {
3591
for (j = i; j < size; j++)
3592
m_set_val(t->matrix, i, j, 0.);
3593
v_set_val(t->vector, i, 0.);
3596
check_relative_width(t, width);
3598
for (i = 0; i < size; i++) {
3599
if (t->fixed_width[i] > 0) {
3600
a = max(t->fixed_width[i], t->minimum_width[i]);
3602
correct_table_matrix(t, i, 1, a, b);
3604
else if (t->fixed_width[i] < 0) {
3605
s = -(double)t->fixed_width[i] / 100.;
3606
b = sigma_td((int)(s * width));
3607
correct_table_matrix2(t, i, 1, s, b);
3611
for (j = 0; j <= cell->maxcell; j++) {
3612
if (cell->fixed_width[j] > 0) {
3613
a = max(cell->fixed_width[j], cell->minimum_width[j]);
3615
correct_table_matrix(t, cell->col[j], cell->colspan[j], a, b);
3617
else if (cell->fixed_width[j] < 0) {
3618
s = -(double)cell->fixed_width[j] / 100.;
3619
b = sigma_td((int)(s * width));
3620
correct_table_matrix2(t, cell->col[j], cell->colspan[j], s, b);
3624
set_table_matrix0(t, width);
3626
if (t->total_width > 0) {
3627
b = sigma_table(width);
3630
b = sigma_table_nw(width);
3632
correct_table_matrix(t, 0, size, width, b);
3636
/* Local Variables: */
3637
/* c-basic-offset: 4 */