1 /* $Id: table.c,v 1.55 2007/05/23 13:07:44 inu 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:\
2412 feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
2413 int width, struct parsed_tag *tag)
2419 struct table_cell *cell = &tbl->cell;
2420 int colspan, rowspan;
2422 int i, j, k, v, v0, w, id;
2423 Str tok, tmp, anchor;
2424 table_attr align, valign;
2428 if (mode->pre_mode & TBLM_PLAIN) {
2429 if (mode->end_tag == cmd) {
2430 mode->pre_mode &= ~TBLM_PLAIN;
2432 feed_table_block_tag(tbl, line, mode, 0, cmd);
2433 return TAG_ACTION_NONE;
2435 return TAG_ACTION_PLAIN;
2437 if (mode->pre_mode & TBLM_INTXTA) {
2440 case HTML_N_TEXTAREA:
2441 table_close_textarea(tbl, mode, width);
2442 if (cmd == HTML_N_TEXTAREA)
2443 return TAG_ACTION_NONE;
2446 return TAG_ACTION_FEED;
2449 if (mode->pre_mode & TBLM_SCRIPT) {
2450 if (mode->end_tag == cmd) {
2451 mode->pre_mode &= ~TBLM_SCRIPT;
2453 return TAG_ACTION_NONE;
2455 return TAG_ACTION_PLAIN;
2457 if (mode->pre_mode & TBLM_STYLE) {
2458 if (mode->end_tag == cmd) {
2459 mode->pre_mode &= ~TBLM_STYLE;
2461 return TAG_ACTION_NONE;
2463 return TAG_ACTION_PLAIN;
2465 /* failsafe: a tag other than <option></option>and </select> in *
2466 * <select> environment is regarded as the end of <select>. */
2467 if (mode->pre_mode & TBLM_INSELECT) {
2471 case HTML_N_SELECT: /* mode->end_tag */
2472 table_close_select(tbl, mode, width);
2473 if (cmd == HTML_N_SELECT)
2474 return TAG_ACTION_NONE;
2477 return TAG_ACTION_FEED;
2480 if (mode->caption) {
2483 case HTML_N_CAPTION:
2485 if (cmd == HTML_N_CAPTION)
2486 return TAG_ACTION_NONE;
2489 return TAG_ACTION_FEED;
2493 if (mode->pre_mode & TBLM_PRE) {
2498 case HTML_N_PRE_INT:
2499 return TAG_ACTION_NONE;
2505 check_rowcol(tbl, mode);
2506 return TAG_ACTION_TABLE;
2508 if (tbl->suspended_data)
2509 check_rowcol(tbl, mode);
2510 return TAG_ACTION_N_TABLE;
2512 if (tbl->col >= 0 && tbl->tabcontentssize > 0)
2513 setwidth(tbl, mode);
2516 tbl->flag |= TBL_IN_ROW;
2517 tbl->flag &= ~TBL_IN_COL;
2520 if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
2523 align = (HTT_LEFT | HTT_TRSET);
2526 align = (HTT_RIGHT | HTT_TRSET);
2529 align = (HTT_CENTER | HTT_TRSET);
2533 if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
2536 valign = (HTT_TOP | HTT_VTRSET);
2539 valign = (HTT_MIDDLE | HTT_VTRSET);
2542 valign = (HTT_BOTTOM | HTT_VTRSET);
2547 if (parsedtag_get_value(tag, ATTR_ID, &p))
2548 tbl->tridvalue[tbl->row] = Strnew_charp(p);
2550 tbl->trattr = align | valign;
2554 prev_col = tbl->col;
2555 if (tbl->col >= 0 && tbl->tabcontentssize > 0)
2556 setwidth(tbl, mode);
2557 if (tbl->row == -1) {
2558 /* for broken HTML... */
2561 tbl->maxrow = tbl->row;
2563 if (tbl->col == -1) {
2564 if (!(tbl->flag & TBL_IN_ROW)) {
2566 tbl->flag |= TBL_IN_ROW;
2568 if (tbl->row > tbl->maxrow)
2569 tbl->maxrow = tbl->row;
2572 check_row(tbl, tbl->row);
2573 while (tbl->tabattr[tbl->row][tbl->col]) {
2576 if (tbl->col > MAXCOL - 1) {
2577 tbl->col = prev_col;
2578 return TAG_ACTION_NONE;
2580 if (tbl->col > tbl->maxcol) {
2581 tbl->maxcol = tbl->col;
2583 colspan = rowspan = 1;
2584 if (tbl->trattr & HTT_TRSET)
2585 align = (tbl->trattr & HTT_ALIGN);
2586 else if (cmd == HTML_TH)
2590 if (tbl->trattr & HTT_VTRSET)
2591 valign = (tbl->trattr & HTT_VALIGN);
2593 valign = HTT_MIDDLE;
2594 if (parsedtag_get_value(tag, ATTR_ROWSPAN, &rowspan)) {
2595 if ((tbl->row + rowspan) >= tbl->max_rowsize)
2596 check_row(tbl, tbl->row + rowspan);
2598 if (parsedtag_get_value(tag, ATTR_COLSPAN, &colspan)) {
2599 if ((tbl->col + colspan) >= MAXCOL) {
2600 /* Can't expand column */
2601 colspan = MAXCOL - tbl->col;
2604 if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
2617 if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
2623 valign = HTT_MIDDLE;
2626 valign = HTT_BOTTOM;
2631 if (parsedtag_exists(tag, ATTR_NOWRAP))
2632 tbl->tabattr[tbl->row][tbl->col] |= HTT_NOWRAP;
2635 if (parsedtag_get_value(tag, ATTR_WIDTH, &v)) {
2638 if (tbl->real_width > 0)
2639 v = -(v * 100) / (tbl->real_width * pixel_per_char);
2641 v = (int)(v / pixel_per_char);
2644 v = RELATIVE_WIDTH(v);
2645 #endif /* not TABLE_EXPAND */
2648 if (parsedtag_get_value(tag, ATTR_ID, &p))
2649 tbl->tabidvalue[tbl->row][tbl->col] = Strnew_charp(p);
2653 /* NOWRAP and WIDTH= conflicts each other */
2654 tbl->tabattr[tbl->row][tbl->col] &= ~HTT_NOWRAP;
2657 tbl->tabattr[tbl->row][tbl->col] &= ~(HTT_ALIGN | HTT_VALIGN);
2658 tbl->tabattr[tbl->row][tbl->col] |= (align | valign);
2662 cell->icell = cell->maxcell + 1;
2663 k = bsearch_2short(colspan, cell->colspan, col, cell->col, MAXCOL,
2664 cell->index, cell->icell);
2665 if (k <= cell->maxcell) {
2667 if (cell->col[i] == col && cell->colspan[i] == colspan)
2670 if (cell->icell > cell->maxcell && cell->icell < MAXCELL) {
2672 cell->col[cell->maxcell] = col;
2673 cell->colspan[cell->maxcell] = colspan;
2674 cell->width[cell->maxcell] = 0;
2675 cell->minimum_width[cell->maxcell] = 0;
2676 cell->fixed_width[cell->maxcell] = 0;
2677 if (cell->maxcell > k) {
2679 for (ii = cell->maxcell; ii > k; ii--)
2680 cell->index[ii] = cell->index[ii - 1];
2682 cell->index[k] = cell->maxcell;
2684 if (cell->icell > cell->maxcell)
2689 v0 = tbl->fixed_width[tbl->col];
2690 if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0)) {
2691 #ifdef FEED_TABLE_DEBUG
2692 fprintf(stderr, "width(%d) = %d\n", tbl->col, v);
2693 #endif /* TABLE_DEBUG */
2694 tbl->fixed_width[tbl->col] = v;
2697 else if (cell->icell >= 0) {
2698 v0 = cell->fixed_width[cell->icell];
2699 if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0))
2700 cell->fixed_width[cell->icell] = v;
2703 for (i = 0; i < rowspan; i++) {
2704 check_row(tbl, tbl->row + i);
2705 for (j = 0; j < colspan; j++) {
2707 tbl->tabattr[tbl->row + i][tbl->col + j] &= ~(HTT_X | HTT_Y);
2709 if (!(tbl->tabattr[tbl->row + i][tbl->col + j] &
2711 tbl->tabattr[tbl->row + i][tbl->col + j] |=
2712 ((i > 0) ? HTT_Y : 0) | ((j > 0) ? HTT_X : 0);
2714 if (tbl->col + j > tbl->maxcol) {
2715 tbl->maxcol = tbl->col + j;
2718 if (tbl->row + i > tbl->maxrow) {
2719 tbl->maxrow = tbl->row + i;
2722 begin_cell(tbl, mode);
2725 setwidth(tbl, mode);
2727 tbl->flag &= ~(TBL_IN_ROW | TBL_IN_COL);
2728 return TAG_ACTION_NONE;
2731 setwidth(tbl, mode);
2732 tbl->flag &= ~TBL_IN_COL;
2733 #ifdef FEED_TABLE_DEBUG
2736 int i = tbl->col, j = tbl->row;
2737 fprintf(stderr, "(a) row,col: %d, %d\n", j, i);
2738 if (tbl->tabdata[j] && tbl->tabdata[j][i]) {
2739 for (it = ((TextList *)tbl->tabdata[j][i])->first;
2741 fprintf(stderr, " [%s] \n", it->ptr);
2745 return TAG_ACTION_NONE;
2752 if (!(tbl->flag & TBL_IN_ROW))
2764 case HTML_PLAINTEXT:
2765 case HTML_PRE_PLAIN:
2766 case HTML_N_PRE_PLAIN:
2767 feed_table_block_tag(tbl, line, mode, 0, cmd);
2770 case HTML_PRE_PLAIN:
2771 mode->pre_mode |= TBLM_PRE;
2774 case HTML_N_PRE_PLAIN:
2775 mode->pre_mode &= ~TBLM_PRE;
2778 mode->pre_mode |= TBLM_PLAIN;
2779 mode->end_tag = HTML_N_LISTING;
2782 mode->pre_mode |= TBLM_PLAIN;
2783 mode->end_tag = HTML_N_XMP;
2785 case HTML_PLAINTEXT:
2786 mode->pre_mode |= TBLM_PLAIN;
2787 mode->end_tag = MAX_HTMLTAG;
2795 feed_table_block_tag(tbl, line, mode, 1, cmd);
2801 feed_table_block_tag(tbl, line, mode, -1, cmd);
2805 if (!(tbl->flag & TBL_IN_ROW))
2808 feed_table_inline_tag(tbl, line, mode, -1);
2812 if (mode->pre_mode & TBLM_NOBR)
2813 return TAG_ACTION_NONE;
2814 mode->pre_mode |= TBLM_NOBR;
2817 if (mode->pre_mode & TBLM_PRE_INT)
2818 return TAG_ACTION_NONE;
2819 mode->pre_mode |= TBLM_PRE_INT;
2820 tbl->linfo.prev_spaces = 0;
2823 mode->nobr_offset = -1;
2824 if (tbl->linfo.length > 0) {
2825 check_minimum0(tbl, tbl->linfo.length);
2826 tbl->linfo.length = 0;
2830 if (!(tbl->flag & TBL_IN_ROW))
2832 feed_table_inline_tag(tbl, line, mode, -1);
2833 if (mode->nobr_level > 0)
2835 if (mode->nobr_level == 0)
2836 mode->pre_mode &= ~TBLM_NOBR;
2838 case HTML_N_PRE_INT:
2839 feed_table_inline_tag(tbl, line, mode, -1);
2840 mode->pre_mode &= ~TBLM_PRE_INT;
2843 check_rowcol(tbl, mode);
2844 w = tbl->fixed_width[tbl->col];
2846 if (tbl->total_width > 0)
2847 w = -tbl->total_width * w / 100;
2849 w = -width * w / 100;
2854 if (tbl->total_width > 0)
2855 w = tbl->total_width;
2859 tok = process_img(tag, w);
2860 feed_table1(tbl, tok, mode, width);
2863 feed_table_block_tag(tbl, "", mode, 0, cmd);
2864 tmp = process_form(tag);
2866 feed_table1(tbl, tmp, mode, width);
2869 feed_table_block_tag(tbl, "", mode, 0, cmd);
2873 tmp = process_input(tag);
2874 feed_table1(tbl, tmp, mode, width);
2877 tmp = process_select(tag);
2879 feed_table1(tbl, tmp, mode, width);
2880 mode->pre_mode |= TBLM_INSELECT;
2881 mode->end_tag = HTML_N_SELECT;
2889 check_rowcol(tbl, mode);
2890 if (tbl->col + 1 <= tbl->maxcol &&
2891 tbl->tabattr[tbl->row][tbl->col + 1] & HTT_X) {
2892 if (cell->icell >= 0 && cell->fixed_width[cell->icell] > 0)
2893 w = cell->fixed_width[cell->icell];
2896 if (tbl->fixed_width[tbl->col] > 0)
2897 w = tbl->fixed_width[tbl->col];
2899 tmp = process_textarea(tag, w);
2901 feed_table1(tbl, tmp, mode, width);
2902 mode->pre_mode |= TBLM_INTXTA;
2903 mode->end_tag = HTML_N_TEXTAREA;
2906 table_close_anchor0(tbl, mode);
2909 parsedtag_get_value(tag, ATTR_HREF, &anchor);
2910 parsedtag_get_value(tag, ATTR_HSEQ, &i);
2912 check_rowcol(tbl, mode);
2914 Str tmp = process_anchor(tag, line);
2915 pushdata(tbl, tbl->row, tbl->col, tmp->ptr);
2918 pushdata(tbl, tbl->row, tbl->col, line);
2920 mode->pre_mode |= TBLM_ANCHOR;
2921 mode->anchor_offset = tbl->tabcontentssize;
2925 suspend_or_pushdata(tbl, line);
2928 switch (displayInsDel) {
2929 case DISPLAY_INS_DEL_SIMPLE:
2930 mode->pre_mode |= TBLM_DEL;
2932 case DISPLAY_INS_DEL_NORMAL:
2933 feed_table_inline_tag(tbl, line, mode, 5); /* [DEL: */
2935 case DISPLAY_INS_DEL_FONTIFY:
2936 feed_table_inline_tag(tbl, line, mode, -1);
2941 switch (displayInsDel) {
2942 case DISPLAY_INS_DEL_SIMPLE:
2943 mode->pre_mode &= ~TBLM_DEL;
2945 case DISPLAY_INS_DEL_NORMAL:
2946 feed_table_inline_tag(tbl, line, mode, 5); /* :DEL] */
2948 case DISPLAY_INS_DEL_FONTIFY:
2949 feed_table_inline_tag(tbl, line, mode, -1);
2954 switch (displayInsDel) {
2955 case DISPLAY_INS_DEL_SIMPLE:
2956 mode->pre_mode |= TBLM_S;
2958 case DISPLAY_INS_DEL_NORMAL:
2959 feed_table_inline_tag(tbl, line, mode, 3); /* [S: */
2961 case DISPLAY_INS_DEL_FONTIFY:
2962 feed_table_inline_tag(tbl, line, mode, -1);
2967 switch (displayInsDel) {
2968 case DISPLAY_INS_DEL_SIMPLE:
2969 mode->pre_mode &= ~TBLM_S;
2971 case DISPLAY_INS_DEL_NORMAL:
2972 feed_table_inline_tag(tbl, line, mode, 3); /* :S] */
2974 case DISPLAY_INS_DEL_FONTIFY:
2975 feed_table_inline_tag(tbl, line, mode, -1);
2981 switch (displayInsDel) {
2982 case DISPLAY_INS_DEL_SIMPLE:
2984 case DISPLAY_INS_DEL_NORMAL:
2985 feed_table_inline_tag(tbl, line, mode, 5); /* [INS:, :INS] */
2987 case DISPLAY_INS_DEL_FONTIFY:
2988 feed_table_inline_tag(tbl, line, mode, -1);
2995 if (!(mode->pre_mode & (TBLM_DEL | TBLM_S)))
2996 feed_table_inline_tag(tbl, line, mode, 1); /* ^, [, ] */
3000 case HTML_TABLE_ALT:
3003 parsedtag_get_value(tag, ATTR_TID, &id);
3004 if (id >= 0 && id < tbl->ntable) {
3005 struct table *tbl1 = tbl->tables[id].ptr;
3006 feed_table_block_tag(tbl, line, mode, 0, cmd);
3007 addcontentssize(tbl, maximum_table_width(tbl1));
3008 check_minimum0(tbl, tbl1->sloppy_width);
3010 w = tbl1->total_width;
3012 colspan = table_colspan(tbl, tbl->row, tbl->col);
3014 if (cell->icell >= 0)
3015 v = cell->fixed_width[cell->icell];
3018 v = tbl->fixed_width[tbl->col];
3019 if (v < 0 && tbl->real_width > 0 && tbl1->real_width > 0)
3020 w = -(tbl1->real_width * 100) / tbl->real_width;
3022 w = tbl1->real_width;
3024 check_minimum0(tbl, w);
3025 else if (w < 0 && v < w) {
3027 if (cell->icell >= 0)
3028 cell->fixed_width[cell->icell] = w;
3031 tbl->fixed_width[tbl->col] = w;
3034 setwidth0(tbl, mode);
3035 clearcontentssize(tbl, mode);
3041 case HTML_N_CAPTION:
3049 case HTML_N_COLGROUP:
3053 mode->pre_mode |= TBLM_SCRIPT;
3054 mode->end_tag = HTML_N_SCRIPT;
3057 mode->pre_mode |= TBLM_STYLE;
3058 mode->end_tag = HTML_N_STYLE;
3061 table_close_anchor0(tbl, mode);
3065 suspend_or_pushdata(tbl, line);
3068 case HTML_N_INTERNAL:
3070 case HTML_N_FORM_INT:
3071 case HTML_INPUT_ALT:
3072 case HTML_N_INPUT_ALT:
3073 case HTML_SELECT_INT:
3074 case HTML_N_SELECT_INT:
3075 case HTML_OPTION_INT:
3076 case HTML_TEXTAREA_INT:
3077 case HTML_N_TEXTAREA_INT:
3082 /* unknown tag: put into table */
3083 return TAG_ACTION_FEED;
3085 return TAG_ACTION_NONE;
3090 feed_table(struct table *tbl, char *line, struct table_mode *mode,
3091 int width, int internal)
3096 struct table_linfo *linfo = &tbl->linfo;
3098 if (*line == '<' && line[1] && REALLY_THE_BEGINNING_OF_A_TAG(line)) {
3099 struct parsed_tag *tag;
3101 tag = parse_tag(&p, internal);
3103 switch (feed_table_tag(tbl, line, mode, width, tag)) {
3104 case TAG_ACTION_NONE:
3106 case TAG_ACTION_N_TABLE:
3108 case TAG_ACTION_TABLE:
3110 case TAG_ACTION_PLAIN:
3112 case TAG_ACTION_FEED:
3114 if (parsedtag_need_reconstruct(tag))
3115 line = parsedtag2str(tag)->ptr;
3119 if (!(mode->pre_mode & (TBLM_PLAIN | TBLM_INTXTA | TBLM_INSELECT |
3120 TBLM_SCRIPT | TBLM_STYLE)))
3125 if (mode->pre_mode & (TBLM_DEL | TBLM_S))
3128 if (mode->caption) {
3129 Strcat_charp(tbl->caption, line);
3132 if (mode->pre_mode & TBLM_SCRIPT)
3134 if (mode->pre_mode & TBLM_STYLE)
3136 if (mode->pre_mode & TBLM_INTXTA) {
3137 feed_textarea(line);
3140 if (mode->pre_mode & TBLM_INSELECT) {
3144 if (!(mode->pre_mode & TBLM_PLAIN) &&
3145 !(*line == '<' && line[strlen(line) - 1] == '>') &&
3146 strchr(line, '&') != NULL) {
3148 for (p = line; *p;) {
3151 if (!strncasecmp(p, "&", 5) ||
3152 !strncasecmp(p, ">", 4) || !strncasecmp(p, "<", 4)) {
3153 /* do not convert */
3154 Strcat_char(tmp, *p);
3160 switch (ec = getescapechar(&p)) {
3162 Strcat_charp(tmp, "<");
3165 Strcat_charp(tmp, ">");
3168 Strcat_charp(tmp, "&");
3171 Strcat_char(tmp, '\n');
3174 r = conv_entity(ec);
3175 if (r != NULL && strlen(r) == 1 &&
3176 ec == (unsigned char)*r) {
3177 Strcat_char(tmp, *r);
3181 Strcat_char(tmp, *q);
3188 Strcat_char(tmp, *p);
3194 if (!(mode->pre_mode & (TBLM_SPECIAL & ~TBLM_NOBR))) {
3195 if (!(tbl->flag & TBL_IN_COL) || linfo->prev_spaces != 0)
3196 while (IS_SPACE(*line))
3200 check_rowcol(tbl, mode);
3201 if (mode->pre_mode & TBLM_NOBR && mode->nobr_offset < 0)
3202 mode->nobr_offset = tbl->tabcontentssize;
3204 /* count of number of spaces skipped in normal mode */
3205 i = skip_space(tbl, line, linfo, !(mode->pre_mode & TBLM_NOBR));
3206 addcontentssize(tbl, visible_length(line) - i);
3207 setwidth(tbl, mode);
3208 pushdata(tbl, tbl->row, tbl->col, line);
3210 else if (mode->pre_mode & TBLM_PRE_INT) {
3211 check_rowcol(tbl, mode);
3212 if (mode->nobr_offset < 0)
3213 mode->nobr_offset = tbl->tabcontentssize;
3214 addcontentssize(tbl, maximum_visible_length(line, tbl->tabcontentssize));
3215 setwidth(tbl, mode);
3216 pushdata(tbl, tbl->row, tbl->col, line);
3219 /* <pre> mode or something like it */
3220 check_rowcol(tbl, mode);
3223 if ((p = strchr(line, '\r')) || (p = strchr(line, '\n'))) {
3224 if (*p == '\r' && p[1] == '\n')
3228 tmp = Strnew_charp_n(line, p - line);
3242 if (mode->pre_mode & TBLM_PLAIN)
3243 i = maximum_visible_length_plain(p, tbl->tabcontentssize);
3245 i = maximum_visible_length(p, tbl->tabcontentssize);
3246 addcontentssize(tbl, i);
3247 setwidth(tbl, mode);
3249 clearcontentssize(tbl, mode);
3250 pushdata(tbl, tbl->row, tbl->col, p);
3257 feed_table1(struct table *tbl, Str tok, struct table_mode *mode, int width)
3265 status = R_ST_NORMAL;
3268 (tokbuf, &line, &status, mode->pre_mode & TBLM_PREMODE, 0))
3269 feed_table(tbl, tokbuf->ptr, mode, width, TRUE);
3273 pushTable(struct table *tbl, struct table *tbl1)
3281 if (tbl->ntable >= tbl->tables_size) {
3282 struct table_in *tmp;
3283 tbl->tables_size += MAX_TABLE_N;
3284 tmp = New_N(struct table_in, tbl->tables_size);
3286 bcopy(tbl->tables, tmp, tbl->ntable * sizeof(struct table_in));
3290 tbl->tables[tbl->ntable].ptr = tbl1;
3291 tbl->tables[tbl->ntable].col = col;
3292 tbl->tables[tbl->ntable].row = row;
3293 tbl->tables[tbl->ntable].indent = tbl->indent;
3294 tbl->tables[tbl->ntable].buf = newTextLineList();
3295 check_row(tbl, row);
3296 if (col + 1 <= tbl->maxcol && tbl->tabattr[row][col + 1] & HTT_X)
3297 tbl->tables[tbl->ntable].cell = tbl->cell.icell;
3299 tbl->tables[tbl->ntable].cell = -1;
3305 correct_table_matrix(struct table *t, int col, int cspan, int a, double b)
3308 int ecol = col + cspan;
3309 double w = 1. / (b * b);
3311 for (i = col; i < ecol; i++) {
3312 v_add_val(t->vector, i, w * a);
3313 for (j = i; j < ecol; j++) {
3314 m_add_val(t->matrix, i, j, w);
3315 m_set_val(t->matrix, j, i, m_entry(t->matrix, i, j));
3322 correct_table_matrix2(struct table *t, int col, int cspan, double s, double b)
3325 int ecol = col + cspan;
3326 int size = t->maxcol + 1;
3327 double w = 1. / (b * b);
3330 for (i = 0; i < size; i++) {
3331 for (j = i; j < size; j++) {
3332 if (i >= col && i < ecol && j >= col && j < ecol)
3333 ss = (1. - s) * (1. - s);
3334 else if ((i >= col && i < ecol) || (j >= col && j < ecol))
3338 m_add_val(t->matrix, i, j, w * ss);
3344 correct_table_matrix3(struct table *t, int col, char *flags, double s,
3349 int size = t->maxcol + 1;
3350 double w = 1. / (b * b);
3351 int flg = (flags[col] == 0);
3353 for (i = 0; i < size; i++) {
3354 if (!((flg && flags[i] == 0) || (!flg && flags[i] != 0)))
3356 for (j = i; j < size; j++) {
3357 if (!((flg && flags[j] == 0) || (!flg && flags[j] != 0)))
3359 if (i == col && j == col)
3360 ss = (1. - s) * (1. - s);
3361 else if (i == col || j == col)
3365 m_add_val(t->matrix, i, j, w * ss);
3371 correct_table_matrix4(struct table *t, int col, int cspan, char *flags,
3376 int ecol = col + cspan;
3377 int size = t->maxcol + 1;
3378 double w = 1. / (b * b);
3380 for (i = 0; i < size; i++) {
3381 if (flags[i] && !(i >= col && i < ecol))
3383 for (j = i; j < size; j++) {
3384 if (flags[j] && !(j >= col && j < ecol))
3386 if (i >= col && i < ecol && j >= col && j < ecol)
3387 ss = (1. - s) * (1. - s);
3388 else if ((i >= col && i < ecol) || (j >= col && j < ecol))
3392 m_add_val(t->matrix, i, j, w * ss);
3398 set_table_matrix0(struct table *t, int maxwidth)
3400 int size = t->maxcol + 1;
3401 int i, j, k, bcol, ecol;
3403 double w0, w1, w, s, b;
3407 #else /* not __GNUC__ */
3409 char expand[MAXCOL];
3410 #endif /* not __GNUC__ */
3411 struct table_cell *cell = &t->cell;
3414 for (i = 0; i < size; i++) {
3415 we[i] = weight(t->tabwidth[i]);
3421 if (cell->necell == 0) {
3422 for (i = 0; i < size; i++) {
3424 b = sigma_td_nw((int)(s * maxwidth));
3425 correct_table_matrix2(t, i, 1, s, b);
3430 bzero(expand, size);
3432 for (k = 0; k < cell->necell; k++) {
3433 j = cell->eindex[k];
3434 bcol = cell->col[j];
3435 ecol = bcol + cell->colspan[j];
3436 width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
3438 for (i = bcol; i < ecol; i++) {
3439 w1 += t->tabwidth[i] + 0.1;
3442 for (i = bcol; i < ecol; i++) {
3443 w = weight(width * (t->tabwidth[i] + 0.1) / w1);
3451 for (i = 0; i < size; i++) {
3459 for (k = 0; k < cell->necell; k++) {
3460 j = cell->eindex[k];
3461 bcol = cell->col[j];
3462 width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
3465 b = sigma_td_nw((int)(s * maxwidth));
3466 correct_table_matrix4(t, bcol, cell->colspan[j], expand, s, b);
3469 for (i = 0; i < size; i++) {
3470 if (expand[i] == 0) {
3471 s = we[i] / max(w1, 1.);
3472 b = sigma_td_nw((int)(s * maxwidth));
3475 s = we[i] / max(w0 - w1, 1.);
3476 b = sigma_td_nw(maxwidth);
3478 correct_table_matrix3(t, i, expand, s, b);
3483 check_relative_width(struct table *t, int maxwidth)
3486 double rel_total = 0;
3487 int size = t->maxcol + 1;
3488 double *rcolwidth = New_N(double, size);
3489 struct table_cell *cell = &t->cell;
3492 for (i = 0; i < size; i++)
3495 for (i = 0; i < size; i++) {
3496 if (t->fixed_width[i] < 0)
3497 rcolwidth[i] = -(double)t->fixed_width[i] / 100.0;
3498 else if (t->fixed_width[i] > 0)
3499 rcolwidth[i] = (double)t->fixed_width[i] / maxwidth;
3503 for (i = 0; i <= cell->maxcell; i++) {
3504 if (cell->fixed_width[i] < 0) {
3505 double w = -(double)cell->fixed_width[i] / 100.0;
3511 for (j = 0; j < cell->colspan[i]; j++) {
3512 if (rcolwidth[j + k] > 0)
3513 r += rcolwidth[j + k];
3517 if (n_leftcell == 0) {
3518 /* w must be identical to r */
3520 cell->fixed_width[i] = -100 * r;
3524 /* make room for the left(width-unspecified) cell */
3525 /* the next formula is an estimation of required width */
3526 w = r * cell->colspan[i] / (cell->colspan[i] - n_leftcell);
3527 cell->fixed_width[i] = -100 * w;
3529 for (j = 0; j < cell->colspan[i]; j++) {
3530 if (rcolwidth[j + k] == 0)
3531 rcolwidth[j + k] = (w - r) / n_leftcell;
3535 else if (cell->fixed_width[i] > 0) {
3540 for (i = 0; i < size; i++)
3541 rel_total += rcolwidth[i];
3543 if ((n_leftcol == 0 && rel_total < 0.9) || 1.1 < rel_total) {
3544 for (i = 0; i < size; i++) {
3545 rcolwidth[i] /= rel_total;
3547 for (i = 0; i < size; i++) {
3548 if (t->fixed_width[i] < 0)
3549 t->fixed_width[i] = -rcolwidth[i] * 100;
3551 for (i = 0; i <= cell->maxcell; i++) {
3552 if (cell->fixed_width[i] < 0) {
3557 for (j = 0; j < cell->colspan[i]; j++)
3558 r += rcolwidth[j + k];
3559 cell->fixed_width[i] = -r * 100;
3566 set_table_matrix(struct table *t, int width)
3568 int size = t->maxcol + 1;
3572 struct table_cell *cell = &t->cell;
3577 t->matrix = m_get(size, size);
3578 t->vector = v_get(size);
3579 for (i = 0; i < size; i++) {
3580 for (j = i; j < size; j++)
3581 m_set_val(t->matrix, i, j, 0.);
3582 v_set_val(t->vector, i, 0.);
3585 check_relative_width(t, width);
3587 for (i = 0; i < size; i++) {
3588 if (t->fixed_width[i] > 0) {
3589 a = max(t->fixed_width[i], t->minimum_width[i]);
3591 correct_table_matrix(t, i, 1, a, b);
3593 else if (t->fixed_width[i] < 0) {
3594 s = -(double)t->fixed_width[i] / 100.;
3595 b = sigma_td((int)(s * width));
3596 correct_table_matrix2(t, i, 1, s, b);
3600 for (j = 0; j <= cell->maxcell; j++) {
3601 if (cell->fixed_width[j] > 0) {
3602 a = max(cell->fixed_width[j], cell->minimum_width[j]);
3604 correct_table_matrix(t, cell->col[j], cell->colspan[j], a, b);
3606 else if (cell->fixed_width[j] < 0) {
3607 s = -(double)cell->fixed_width[j] / 100.;
3608 b = sigma_td((int)(s * width));
3609 correct_table_matrix2(t, cell->col[j], cell->colspan[j], s, b);
3613 set_table_matrix0(t, width);
3615 if (t->total_width > 0) {
3616 b = sigma_table(width);
3619 b = sigma_table_nw(width);
3621 correct_table_matrix(t, 0, size, width, b);
3625 /* Local Variables: */
3626 /* c-basic-offset: 4 */