diff options
author | Akinori Ito <aito@eie.yz.yamagata-u.ac.jp> | 2001-11-09 04:59:17 +0000 |
---|---|---|
committer | Akinori Ito <aito@eie.yz.yamagata-u.ac.jp> | 2001-11-09 04:59:17 +0000 |
commit | 6c63633545c254dc085402e0f927a6826d1dd229 (patch) | |
tree | 0126fb5598304c713ea1276e294da9098b5df3b4 /table.c.0 | |
parent | Initial revision (diff) | |
download | w3m-6c63633545c254dc085402e0f927a6826d1dd229.tar.gz w3m-6c63633545c254dc085402e0f927a6826d1dd229.zip |
Updates from 0.2.1 into 0.2.1-inu-1.5release-0-2-1-inu-1-5
Diffstat (limited to 'table.c.0')
-rw-r--r-- | table.c.0 | 2878 |
1 files changed, 0 insertions, 2878 deletions
diff --git a/table.c.0 b/table.c.0 deleted file mode 100644 index f3cacb1..0000000 --- a/table.c.0 +++ /dev/null @@ -1,2878 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; tab-width: 8; -*- */ -/* $Id: table.c.0,v 1.1 2001/11/08 05:15:52 a-ito Exp $ */ -/* - * HTML table - */ -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <math.h> -#ifdef __EMX__ -#include <strings.h> -#endif /* __EMX__ */ - -#include "fm.h" -#include "html.h" -#include "parsetag.h" -#include "Str.h" -#include "myctype.h" - -#ifdef KANJI_SYMBOLS -static char *rule[] = -{"¨«", "¨§", "¨¨", "¨£", "¨©", "¨¢", "¨¤", "07", "¨ª", "¨¦", "¨¡", "0B", "¨¥", "0D", "0E", " "}; -static char *ruleB[] = -{"00", "¨·", "¨¸", "¨®", "¨¹", "¨", "¨¯", "07", "¨º", "¨±", "¨¬", "0B", "¨°", "0D", "0E", " "}; -#define TN_VERTICALBAR "¨¢" -#define HORIZONTALBAR "¨¬" -#define RULE_WIDTH 2 -#else /* not KANJI_SYMBOLS */ -static char *rule[] = -{ - "<_RULE TYPE=0>+</_RULE>", - "<_RULE TYPE=1>+</_RULE>", - "<_RULE TYPE=2>+</_RULE>", - "<_RULE TYPE=3>+</_RULE>", - "<_RULE TYPE=4>+</_RULE>", - "<_RULE TYPE=5>|</_RULE>", - "<_RULE TYPE=6>+</_RULE>", - "<_RULE TYPE=7>07</_RULE>", - "<_RULE TYPE=8>+</_RULE>", - "<_RULE TYPE=9>+</_RULE>", - "<_RULE TYPE=10>-</_RULE>", - "<_RULE TYPE=11>0B</_RULE>", - "<_RULE TYPE=12>+</_RULE>", - "<_RULE TYPE=13>0D</_RULE>", - "<_RULE TYPE=14>0E</_RULE>", - "<_RULE TYPE=15> </_RULE>"}; -static char **ruleB = rule; -#define TN_VERTICALBAR "<_RULE TYPE=5>|</_RULE>" -#define HORIZONTALBAR "<_RULE TYPE=10>-</_RULE>" -#define RULE_WIDTH 1 -#endif /* not KANJI_SYMBOLS */ - -#define RULE(mode) (((mode)==BORDER_THICK)?ruleB:rule) -#define TK_VERTICALBAR(mode) (RULE(mode)[5]) - -#define BORDERWIDTH 2 -#define BORDERHEIGHT 1 -#define NOBORDERWIDTH 1 -#define NOBORDERHEIGHT 0 - -#define HTT_X 1 -#define HTT_Y 2 -#define HTT_ALIGN 0x30 -#define HTT_LEFT 0x00 -#define HTT_CENTER 0x10 -#define HTT_RIGHT 0x20 -#define HTT_TRSET 0x40 -#ifdef NOWRAP -#define HTT_NOWRAP 4 -#endif /* NOWRAP */ -#define TAG_IS(s,tag,len) (strncasecmp(s,tag,len)==0&&(s[len] == '>' || IS_SPACE((int)s[len]))) - -#ifndef max -#define max(a,b) ((a) > (b) ? (a) : (b)) -#endif /* not max */ -#ifndef min -#define min(a,b) ((a) > (b) ? (b) : (a)) -#endif /* not min */ -#ifndef abs -#define abs(a) ((a) >= 0. ? (a) : -(a)) -#endif /* not abs */ - -#ifdef MATRIX -#ifndef MESCHACH -#include "matrix.c" -#endif /* not MESCHACH */ -#endif /* MATRIX */ - -#ifdef MATRIX -int correct_table_matrix(struct table *, int, int, int, double); -void set_table_matrix(struct table *, int); -#endif /* MATRIX */ - -#ifdef MATRIX -static double -weight(int x) -{ - - if (x < COLS) - return (double) x; - else - return COLS * (log((double) x / COLS) + 1.); -} - -static double -weight2(int a) -{ - return (double) a / COLS * 4 + 1.; -} - -#define sigma_td(a) (0.5*weight2(a)) /* <td width=...> */ -#define sigma_td_nw(a) (32*weight2(a)) /* <td ...> */ -#define sigma_table(a) (0.25*weight2(a)) /* <table width=...> */ -#define sigma_table_nw(a) (2*weight2(a)) /* <table...> */ -#else /* not MATRIX */ -#define LOG_MIN 1.0 -static double -weight3(int x) -{ - if (x < 0.1) - return 0.1; - if (x < LOG_MIN) - return (double) x; - else - return LOG_MIN * (log((double) x / LOG_MIN) + 1.); -} -#endif /* not MATRIX */ - -static int -dsort_index(short e1, short *ent1, short e2, short *ent2, int base, - char *index, int nent) -{ - int n = nent; - int k = 0; - - int e = e1 * base + e2; - while (n > 0) { - int nn = n / 2; - int idx = index[k + nn]; - int ne = ent1[idx] * base + ent2[idx]; - if (ne == e) { - k += nn; - break; - } - else if (ne < e) { - n -= nn + 1; - k += nn + 1; - } - else { - n = nn; - } - } - return k; -} - -static int -fsort_index(double e, double *ent, char *index, int nent) -{ - int n = nent; - int k = 0; - - while (n > 0) { - int nn = n / 2; - int idx = index[k + nn]; - double ne = ent[idx]; - if (ne == e) { - k += nn; - break; - } - else if (ne > e) { - n -= nn + 1; - k += nn + 1; - } - else { - n = nn; - } - } - return k; -} - -static void -dv2sv(double *dv, short *iv, int size) -{ - int i, k, iw; - char *index; - double *edv; - double w = 0., x; - - index = NewAtom_N(char, size); - edv = NewAtom_N(double, size); - for (i = 0; i < size; i++) { - iv[i] = ceil(dv[i]); - edv[i] = (double) iv[i] - dv[i]; - } - - w = 0.; - for (k = 0; k < size; k++) { - x = edv[k]; - w += x; - i = fsort_index(x, edv, index, k); - if (k > i) - bcopy(index + i, index + i + 1, k - i); - index[i] = k; - } - iw = min((int) (w + 0.5), size); - if (iw == 0) - return; - x = edv[(int) index[iw - 1]]; - for (i = 0; i < size; i++) { - k = index[i]; - if (i >= iw && abs(edv[k] - x) > 1e-6) - break; - iv[k]--; - } -} - -static int -table_colspan(struct table *t, int row, int col) -{ - int i; - for (i = col + 1; i <= t->maxcol && (t->tabattr[row][i] & HTT_X); i++); - return i - col; -} - -static int -table_rowspan(struct table *t, int row, int col) -{ - int i; - if (!t->tabattr[row]) - return 0; - for (i = row + 1; i <= t->maxrow && t->tabattr[i] && - (t->tabattr[i][col] & HTT_Y); i++); - return i - row; -} - -static int -minimum_cellspacing(int border_mode) -{ - switch (border_mode) { - case BORDER_THIN: - case BORDER_THICK: - case BORDER_NOWIN: - return RULE_WIDTH; - case BORDER_NONE: - return 1; - default: - /* not reached */ - return 0; - } -} - -static int -table_border_width(struct table *t) -{ - switch (t->border_mode) { - case BORDER_THIN: - case BORDER_THICK: - return t->maxcol * t->cellspacing + 2 * (RULE_WIDTH + t->cellpadding); - case BORDER_NOWIN: - case BORDER_NONE: - return t->maxcol * t->cellspacing; - default: - /* not reached */ - return 0; - } -} - -struct table * -newTable() -{ - struct table *t; - int i, j; - - t = New(struct table); - t->max_rowsize = MAXROW; - t->tabdata = New_N(TextList **, MAXROW); - t->tabattr = New_N(table_attr *, MAXROW); - t->tabheight = NewAtom_N(short, MAXROW); -#ifdef ID_EXT - t->tabidvalue = New_N(Str *, MAXROW); - t->tridvalue = New_N(Str, MAXROW); -#endif /* ID_EXT */ - - for (i = 0; i < MAXROW; i++) { - t->tabdata[i] = NULL; - t->tabattr[i] = 0; - t->tabheight[i] = 0; -#ifdef ID_EXT - t->tabidvalue[i] = NULL; - t->tridvalue[i] = NULL; -#endif /* ID_EXT */ - } - for (j = 0; j < MAXCOL; j++) { - t->tabwidth[j] = 0; - t->minimum_width[j] = 0; - t->fixed_width[j] = 0; - } - t->cell.maxcell = -1; - t->cell.icell = -1; - t->tabcontentssize = 0; - t->indent = 0; - t->ntable = 0; - t->tables_size = 0; - t->tables = NULL; -#ifdef MATRIX - t->matrix = NULL; - t->vector = NULL; -#endif /* MATRIX */ - t->linfo.prev_ctype = PC_ASCII; - t->linfo.prev_spaces = -1; - t->linfo.prevchar = ' '; - t->trattr = 0; - - t->status = R_ST_NORMAL; - t->suspended_input = Strnew(); - t->caption = Strnew(); -#ifdef ID_EXT - t->id = NULL; -#endif - return t; -} - -static void -check_row(struct table *t, int row) -{ - int i, r; - TextList ***tabdata; - table_attr **tabattr; - short *tabheight; -#ifdef ID_EXT - Str **tabidvalue; - Str *tridvalue; -#endif /* ID_EXT */ - - if (row >= t->max_rowsize) { - r = max(t->max_rowsize * 2, row + 1); - tabdata = New_N(TextList **, r); - tabattr = New_N(table_attr *, r); - tabheight = New_N(short, r); -#ifdef ID_EXT - tabidvalue = New_N(Str *, r); - tridvalue = New_N(Str, r); -#endif /* ID_EXT */ - for (i = 0; i < t->max_rowsize; i++) { - tabdata[i] = t->tabdata[i]; - tabattr[i] = t->tabattr[i]; - tabheight[i] = t->tabheight[i]; -#ifdef ID_EXT - tabidvalue[i] = t->tabidvalue[i]; - tridvalue[i] = t->tridvalue[i]; -#endif /* ID_EXT */ - } - for (; i < r; i++) { - tabdata[i] = NULL; - tabattr[i] = NULL; - tabheight[i] = 0; -#ifdef ID_EXT - tabidvalue[i] = NULL; - tridvalue[i] = NULL; -#endif /* ID_EXT */ - } - t->tabdata = tabdata; - t->tabattr = tabattr; - t->tabheight = tabheight; -#ifdef ID_EXT - t->tabidvalue = tabidvalue; - t->tridvalue = tridvalue; -#endif /* ID_EXT */ - t->max_rowsize = r; - } - - if (t->tabdata[row] == NULL) { - t->tabdata[row] = New_N(TextList *, MAXCOL); - t->tabattr[row] = NewAtom_N(table_attr, MAXCOL); -#ifdef ID_EXT - t->tabidvalue[row] = New_N(Str, MAXCOL); -#endif /* ID_EXT */ - for (i = 0; i < MAXCOL; i++) { - t->tabdata[row][i] = NULL; - t->tabattr[row][i] = 0; -#ifdef ID_EXT - t->tabidvalue[row][i] = NULL; -#endif /* ID_EXT */ - } - } -} - -void -pushdata(struct table *t, int row, int col, char *data) -{ - check_row(t, row); - if (t->tabdata[row][col] == NULL) - t->tabdata[row][col] = newTextList(); - - pushText(t->tabdata[row][col], data); -} - -int visible_length_offset = 0; -int -visible_length(char *str) -{ - int len = 0; - int status = R_ST_NORMAL; - int prev_status = status; - Str tagbuf = Strnew(); - char *t, *r2; - struct parsed_tagarg *t_arg, *tt; - int amp_len; - - t = str; - while (*str) { - prev_status = status; - len += next_status(*str, &status); - if (status == R_ST_TAG0) { - Strclear(tagbuf); - Strcat_char(tagbuf, *str); - } - else if (status == R_ST_TAG || status == R_ST_DQUOTE || status == R_ST_QUOTE || status == R_ST_EQL) { - Strcat_char(tagbuf, *str); - } - else if (status == R_ST_AMP) { - if (prev_status == R_ST_NORMAL) { - Strclear(tagbuf); - amp_len = 0; - } - else { - Strcat_char(tagbuf, *str); - len++; - amp_len++; - } - } - else if (status == R_ST_NORMAL && prev_status == R_ST_AMP) { - Strcat_char(tagbuf, *str); - r2 = tagbuf->ptr; - t = getescapecmd(&r2); - len += strlen(t) - 1 - amp_len; - if (*r2 != '\0') { - str -= strlen(r2); - } - } - else if (status == R_ST_NORMAL && ST_IS_REAL_TAG(prev_status)) { - Strcat_char(tagbuf, *str); - if (TAG_IS(tagbuf->ptr, "<img", 4)) { - int anchor_len = 0; - t_arg = parse_tag(tagbuf->ptr + 5); - for (tt = t_arg; tt; tt = tt->next) { - if (strcasecmp(tt->arg, "src") == 0 && tt->value && anchor_len == 0) { - r2 = tt->value + strlen(tt->value) - 1; - while (tt->value < r2 && *r2 != '/') - r2--; - if (*r2 == '/') - r2++; - while (*r2 && *r2 != '.') { - r2++; - anchor_len++; - } - anchor_len += 2; - } - else if (strcasecmp(tt->arg, "alt") == 0 && tt->value) { - anchor_len = strlen(tt->value) + 1; - break; - } - } - len += anchor_len; - } - else if (TAG_IS(tagbuf->ptr, "<input", 6)) { - int width = 20; - int valuelen = 1; - int input_type = FORM_INPUT_TEXT; - t_arg = parse_tag(tagbuf->ptr + 7); - for (tt = t_arg; tt; tt = tt->next) { - if (strcasecmp(tt->arg, "type") == 0 && tt->value) { - input_type = formtype(tt->value); - } - else if (strcasecmp(tt->arg, "value") == 0 && tt->value) { - valuelen = strlen(tt->value); - } - else if (strcasecmp(tt->arg, "width") == 0 && tt->value) { - width = atoi(tt->value); - } - } - switch (input_type) { - case FORM_INPUT_TEXT: - case FORM_INPUT_FILE: - case FORM_INPUT_PASSWORD: - len += width + 2; - break; - case FORM_INPUT_SUBMIT: - case FORM_INPUT_RESET: - case FORM_INPUT_IMAGE: - case FORM_INPUT_BUTTON: - len += valuelen + 2; - break; - case FORM_INPUT_CHECKBOX: - case FORM_INPUT_RADIO: - len += 3; - } - } - else if (TAG_IS(tagbuf->ptr, "<textarea", 9)) { - int width = 20; - t_arg = parse_tag(tagbuf->ptr + 7); - for (tt = t_arg; tt; tt = tt->next) { - if (strcasecmp(tt->arg, "cols") == 0 && tt->value) { - width = atoi(tt->value); - } - } - len += width + 2; - } - else if (TAG_IS(tagbuf->ptr, "<option", 7)) - len += 3; - } - else if (*str == '\t') { - len--; - do { - len++; - } while ((visible_length_offset + len) % Tabstop != 0); - } - str++; - } - if (status == R_ST_AMP) { - r2 = tagbuf->ptr; - t = getescapecmd(&r2); - len += strlen(t) - 1 - amp_len; - if (*r2 != '\0') { - len += strlen(r2); - } - } - return len; -} - -int -maximum_visible_length(char *str) -{ - int maxlen, len; - char *p; - - for (p = str; *p && *p != '\t'; p++); - - visible_length_offset = 0; - maxlen = visible_length(str); - - if (*p == '\0') - return maxlen; - - for (visible_length_offset = 1; visible_length_offset < Tabstop; - visible_length_offset++) { - len = visible_length(str); - if (maxlen < len) { - maxlen = len; - break; - } - } - return maxlen; -} - -char * -align(char *str, int width, int mode) -{ - int i, l, l1, l2; - Str buf = Strnew(); - - if (str == NULL || *str == '\0') { - for (i = 0; i < width; i++) - Strcat_char(buf, ' '); - return buf->ptr; - } - l = width - visible_length(str); - switch (mode) { - case ALIGN_CENTER: - l1 = l / 2; - l2 = l - l1; - for (i = 0; i < l1; i++) - Strcat_char(buf, ' '); - Strcat_charp(buf, str); - for (i = 0; i < l2; i++) - Strcat_char(buf, ' '); - return buf->ptr; - case ALIGN_LEFT: - Strcat_charp(buf, str); - for (i = 0; i < l; i++) - Strcat_char(buf, ' '); - return buf->ptr; - case ALIGN_RIGHT: - for (i = 0; i < l; i++) - Strcat_char(buf, ' '); - Strcat_charp(buf, str); - return buf->ptr; - } - return Strnew_charp(str)->ptr; -} - -void -print_item(struct table *t, - int row, int col, int width, - Str buf) -{ - int alignment; - char *p; - - if (t->tabdata[row]) - p = popText(t->tabdata[row][col]); - else - p = NULL; - - if (p != NULL) { - check_row(t, row); - alignment = ALIGN_CENTER; - if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_LEFT) - alignment = ALIGN_LEFT; - else if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_RIGHT) - alignment = ALIGN_RIGHT; - else if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_CENTER) - alignment = ALIGN_CENTER; - Strcat_charp(buf, align(p, width, alignment)); - } - else - Strcat_charp(buf, align(NULL, width, ALIGN_CENTER)); -} - - -#define T_TOP 0 -#define T_MIDDLE 1 -#define T_BOTTOM 2 - -void -print_sep(struct table *t, - int row, int type, int maxcol, - Str buf) -{ - int forbid; - char **rulep; - int i, j, k, l, m; - -#if defined(__EMX__)&&!defined(JP_CHARSET) - if(CodePage==850){ - ruleB = ruleB850; - rule = rule850; - } -#endif - if (row >= 0) - check_row(t, row); - check_row(t, row + 1); - if ((type == T_TOP || type == T_BOTTOM) && t->border_mode == BORDER_THICK) { - rulep = ruleB; - } - else { - rulep = rule; - } - forbid = 1; - if (type == T_TOP) - forbid |= 2; - else if (type == T_BOTTOM) - forbid |= 8; - else if (t->tabattr[row + 1][0] & HTT_Y) { - forbid |= 4; - } - if (t->border_mode != BORDER_NOWIN) - Strcat_charp(buf, RULE(t->border_mode)[forbid]); - for (i = 0; i <= maxcol; i++) { - forbid = 10; - if (type != T_BOTTOM && (t->tabattr[row + 1][i] & HTT_Y)) { - if (t->tabattr[row + 1][i] & HTT_X) { - goto do_last_sep; - } - else { - for (k = row; k >= 0 && t->tabattr[k] && (t->tabattr[k][i] & HTT_Y); k--); - m = t->tabwidth[i] + 2 * t->cellpadding; - for (l = i + 1; l <= t->maxcol && (t->tabattr[row][l] & HTT_X); l++) - m += t->tabwidth[l] + t->cellspacing; - print_item(t, k, i, m, buf); - } - } - else { - for (j = 0; j < t->tabwidth[i] + 2 * t->cellpadding; j += RULE_WIDTH) { - Strcat_charp(buf, rulep[forbid]); - } - } - do_last_sep: - if (i < maxcol) { - forbid = 0; - if (type == T_TOP) - forbid |= 2; - else if (t->tabattr[row][i + 1] & HTT_X) { - forbid |= 2; - } - if (type == T_BOTTOM) - forbid |= 8; - else { - if (t->tabattr[row + 1][i + 1] & HTT_X) { - forbid |= 8; - } - if (t->tabattr[row + 1][i + 1] & HTT_Y) { - forbid |= 4; - } - if (t->tabattr[row + 1][i] & HTT_Y) { - forbid |= 1; - } - } - if (forbid != 15) /* forbid==15 means 'no rule at all' */ - Strcat_charp(buf, rulep[forbid]); - } - } - forbid = 4; - if (type == T_TOP) - forbid |= 2; - if (type == T_BOTTOM) - forbid |= 8; - if (t->tabattr[row + 1][maxcol] & HTT_Y) { - forbid |= 1; - } - if (t->border_mode != BORDER_NOWIN) - Strcat_charp(buf, RULE(t->border_mode)[forbid]); - Strcat_charp(buf, "<eol>"); -} - -static int -get_spec_cell_width(struct table *tbl, int row, int col) -{ - int i, w; - - w = tbl->tabwidth[col]; - for (i = col + 1; i <= tbl->maxcol; i++) { - check_row(tbl, row); - if (tbl->tabattr[row][i] & HTT_X) - w += tbl->tabwidth[i] + tbl->cellspacing; - else - break; - } - return w; -} - -void -do_refill(struct table *tbl, int row, int col) -{ - TextList *orgdata; - TextListItem *l; - struct readbuffer obuf; - struct html_feed_environ h_env; - struct environment envs[MAX_ENV_LEVEL]; - - if (tbl->tabdata[row] == NULL || - tbl->tabdata[row][col] == NULL) - return; - orgdata = tbl->tabdata[row][col]; - tbl->tabdata[row][col] = newTextList(); - - init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL, tbl->tabdata[row][col], - tbl->tabwidth[col], 0); - h_env.limit = get_spec_cell_width(tbl, row, col); - for (l = orgdata->first; l != NULL; l = l->next) { - if (TAG_IS(l->ptr, "<dummy_table", 12)) { - struct parsed_tagarg *t_arg, *t; - int id = -1; - t_arg = parse_tag(l->ptr + 12); - for (t = t_arg; t; t = t->next) { - if (!strcasecmp(t->arg, "id") && t->value) { - id = atoi(t->value); - break; - } - } - if (id >= 0) { - int alignment; - TextListItem *ti; - save_fonteffect(&h_env, h_env.obuf); - flushline(&h_env, &obuf, 0, 0, h_env.limit); - - if (RB_GET_ALIGN(h_env.obuf) == RB_CENTER) - alignment = ALIGN_CENTER; - else if (RB_GET_ALIGN(h_env.obuf) == RB_RIGHT) - alignment = ALIGN_RIGHT; - else - alignment = ALIGN_LEFT; - - if (alignment == ALIGN_LEFT) { - appendTextList(h_env.buf, tbl->tables[id].buf); - } - else { - for (ti = tbl->tables[id].buf->first; ti != NULL; ti = ti->next) { - pushText(h_env.buf, align(ti->ptr, h_env.limit, alignment)); - } - } - restore_fonteffect(&h_env, h_env.obuf); - } - } - else - HTMLlineproc1(l->ptr, &h_env); - } - flushline(&h_env, &obuf, 0, 0, h_env.limit); -} - -static void -check_cell_width(short *tabwidth, short *cellwidth, - short *col, short *colspan, short maxcell, - char *index, int space, int dir) -{ - int i, j, k, bcol, ecol; - int swidth, width; - - for (k = 0; k <= maxcell; k++) { - j = index[k]; - if (cellwidth[j] <= 0) - continue; - bcol = col[j]; - ecol = bcol + colspan[j]; - swidth = 0; - for (i = bcol; i < ecol; i++) - swidth += tabwidth[i]; - - width = cellwidth[j] - (colspan[j] - 1) * space; - if (width > swidth) { - int w = (width - swidth) / colspan[j]; - int r = (width - swidth) % colspan[j]; - for (i = bcol; i < ecol; i++) - tabwidth[i] += w; - /* dir {0: horizontal, 1: vertical} */ - if (dir == 1 && r > 0) - r = colspan[j]; - for (i = 1; i <= r; i++) - tabwidth[ecol - i]++; - } - } -} - -void -check_minimum_width(struct table *t, short *tabwidth) -{ - int i; - struct table_cell *cell = &t->cell; - - for (i = 0; i <= t->maxcol; i++) { - if (tabwidth[i] < t->minimum_width[i]) - tabwidth[i] = t->minimum_width[i]; - } - - check_cell_width(tabwidth, cell->minimum_width, cell->col, cell->colspan, - cell->maxcell, cell->index, t->cellspacing, 0); -} - -void -check_maximum_width(struct table *t) -{ - struct table_cell *cell = &t->cell; -#ifdef MATRIX - int i, j, bcol, ecol; - int swidth, width; - - cell->necell = 0; - for (j = 0; j <= cell->maxcell; j++) { - bcol = cell->col[j]; - ecol = bcol + cell->colspan[j]; - swidth = 0; - for (i = bcol; i < ecol; i++) - swidth += t->tabwidth[i]; - - width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing; - if (width > swidth) { - cell->eindex[cell->necell] = j; - cell->necell++; - } - } -#else /* not MATRIX */ - check_cell_width(t->tabwidth, cell->width, cell->col, cell->colspan, - cell->maxcell, cell->index, t->cellspacing, 0); - check_minimum_width(t, t->tabwidth); -#endif /* not MATRIX */ -} - - -#ifdef MATRIX -static int -recalc_width(int old, int delta, double rat) -{ - double w = rat * old; - double ww = (double) delta; - if (w > 0.) { - if (ww < 0.) - ww = 0.; - ww += 0.2; - } - else { - if (ww > 0.) - ww = 0.; - ww -= 1.0; - } - if (w > ww) - return (int) (ww / rat); - return old; -} - -static int -check_compressible_cell(struct table *t, MAT * minv, - short *newwidth, short *swidth, short *cwidth, - int totalwidth, - int icol, int icell, double sxx, int corr) -{ - struct table_cell *cell = &t->cell; - int i, j, k, m, bcol, ecol; - int delta, dmax, dmin, owidth; - double sxy; - - if (sxx < 10.) - return corr; - - if (icol >= 0) { - owidth = newwidth[icol]; - delta = newwidth[icol] - t->tabwidth[icol]; - bcol = icol; - ecol = bcol + 1; - } - else if (icell >= 0) { - owidth = swidth[icell]; - delta = swidth[icell] - cwidth[icell]; - bcol = cell->col[icell]; - ecol = bcol + cell->colspan[icell]; - } - else { - owidth = totalwidth; - delta = totalwidth; - bcol = 0; - ecol = t->maxcol + 1; - } - - dmin = delta; - dmax = 0; - for (k = 0; k <= cell->maxcell; k++) { - int bcol1, ecol1; - if (dmin <= 0) - return corr; - j = cell->index[k]; - if (icol < 0 && j == icell) - continue; - bcol1 = cell->col[j]; - ecol1 = bcol1 + cell->colspan[j]; - sxy = 0.; - for (m = bcol1; m < ecol1; m++) { - for (i = bcol; i < ecol; i++) - sxy += m_entry(minv, i, m); - } - if (fabs(delta * sxy / sxx) < 0.5) - continue; - if (sxy > 0.) - dmin = recalc_width(dmin, swidth[j] - cwidth[j], sxy / sxx); - else - dmax = recalc_width(dmax, swidth[j] - cwidth[j], sxy / sxx); - } - for (m = 0; m <= t->maxcol; m++) { - if (dmin <= 0) - return corr; - if (icol >= 0 && m == icol) - continue; - sxy = 0.; - for (i = bcol; i < ecol; i++) - sxy += m_entry(minv, i, m); - if (fabs(delta * sxy / sxx) < 0.5) - continue; - if (sxy > 0.) - dmin = recalc_width(dmin, newwidth[m] - t->tabwidth[m], sxy / sxx); - else - dmax = recalc_width(dmax, newwidth[m] - t->tabwidth[m], sxy / sxx); - } - if (dmax > 0 && dmin > dmax) - dmin = dmax; - if (dmin > 1) { - correct_table_matrix(t, bcol, ecol - bcol, owidth - dmin, 1.); - corr++; - } - return corr; -} - -#define MAX_ITERATION 3 -int -check_table_width(struct table *t, short *newwidth, MAT * minv, int itr) -{ - int i, j, k, m, bcol, ecol; - int corr = 0; - struct table_cell *cell = &t->cell; -#ifdef __GNUC__ - short orgwidth[t->maxcol + 1]; - short cwidth[cell->maxcell + 1], swidth[cell->maxcell + 1]; -#else /* __GNUC__ */ - short orgwidth[MAXCOL]; - short cwidth[MAXCELL], swidth[MAXCELL]; -#endif /* __GNUC__ */ - int twidth; - double sxy, *Sxx, stotal; - - twidth = 0; - stotal = 0.; - for (i = 0; i <= t->maxcol; i++) { - twidth += newwidth[i]; - stotal += m_entry(minv, i, i); - for (m = 0; m < i; m++) { - stotal += 2 * m_entry(minv, i, m); - } - } - - Sxx = NewAtom_N(double, cell->maxcell + 1); - for (k = 0; k <= cell->maxcell; k++) { - j = cell->index[k]; - bcol = cell->col[j]; - ecol = bcol + cell->colspan[j]; - swidth[j] = 0; - for (i = bcol; i < ecol; i++) - swidth[j] += newwidth[i]; - cwidth[j] = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing; - Sxx[j] = 0.; - for (i = bcol; i < ecol; i++) { - Sxx[j] += m_entry(minv, i, i); - for (m = bcol; m <= ecol; m++) { - if (m < i) - Sxx[j] += 2 * m_entry(minv, i, m); - } - } - } - - /* compress table */ - corr = check_compressible_cell(t, minv, newwidth, swidth, cwidth, twidth, - -1, -1, stotal, corr); - if (itr < MAX_ITERATION && corr > 0) - return corr; - - /* compress multicolumn cell */ - for (k = cell->maxcell; k >= 0; k--) { - j = cell->index[k]; - corr = check_compressible_cell(t, minv, newwidth, swidth, cwidth, twidth, - -1, j, Sxx[j], corr); - if (itr < MAX_ITERATION && corr > 0) - return corr; - } - - /* compress single column cell */ - for (i = 0; i <= t->maxcol; i++) { - corr = check_compressible_cell(t, minv, newwidth, swidth, cwidth, twidth, - i, -1, m_entry(minv, i, i), corr); - if (itr < MAX_ITERATION && corr > 0) - return corr; - } - - - for (i = 0; i <= t->maxcol; i++) - orgwidth[i] = newwidth[i]; - - check_minimum_width(t, newwidth); - - for (i = 0; i <= t->maxcol; i++) { - double sx = sqrt(m_entry(minv, i, i)); - if (sx < 0.1) - continue; - if (orgwidth[i] < t->minimum_width[i] && - newwidth[i] == t->minimum_width[i]) { - double w = (sx > 0.5) ? 0.5 : sx * 0.2; - sxy = 0.; - for (m = 0; m <= t->maxcol; m++) { - if (m == i) - continue; - sxy += m_entry(minv, i, m); - } - if (sxy <= 0.) { - correct_table_matrix(t, i, 1, t->minimum_width[i], w); - corr++; - } - } - } - - for (k = 0; k <= cell->maxcell; k++) { - int nwidth = 0, mwidth; - double sx; - - j = cell->index[k]; - sx = sqrt(Sxx[j]); - if (sx < 0.1) - continue; - bcol = cell->col[j]; - ecol = bcol + cell->colspan[j]; - for (i = bcol; i < ecol; i++) - nwidth += newwidth[i]; - mwidth = cell->minimum_width[j] - (cell->colspan[j] - 1) * t->cellspacing; - if (mwidth > swidth[j] && mwidth == nwidth) { - double w = (sx > 0.5) ? 0.5 : sx * 0.2; - - sxy = 0.; - for (i = bcol; i < ecol; i++) { - for (m = 0; m <= t->maxcol; m++) { - if (m >= bcol && m < ecol) - continue; - sxy += m_entry(minv, i, m); - } - } - if (sxy <= 0.) { - correct_table_matrix(t, bcol, cell->colspan[j], mwidth, w); - corr++; - } - } - } - - if (itr >= MAX_ITERATION) - return 0; - else - return corr; -} - -#else /* not MATRIX */ -void -set_table_width(struct table *t, short *newwidth, int maxwidth) -{ - int i, j, k, bcol, ecol; - struct table_cell *cell = &t->cell; - char *fixed; - int swidth, fwidth, width, nvar; - double s; - double *dwidth; - int try_again; - - fixed = NewAtom_N(char, t->maxcol + 1); - bzero(fixed, t->maxcol + 1); - dwidth = NewAtom_N(double, t->maxcol + 1); - - for (i = 0; i <= t->maxcol; i++) { - dwidth[i] = 0.0; - if (t->fixed_width[i] < 0) { - t->fixed_width[i] = -t->fixed_width[i] * maxwidth / 100; - } - if (t->fixed_width[i] > 0) { - newwidth[i] = t->fixed_width[i]; - fixed[i] = 1; - } - else - newwidth[i] = 0; - if (newwidth[i] < t->minimum_width[i]) - newwidth[i] = t->minimum_width[i]; - } - - for (k = 0; k <= cell->maxcell; k++) { - j = cell->index[k]; - bcol = cell->col[j]; - ecol = bcol + cell->colspan[j]; - - if (cell->fixed_width[j] < 0) - cell->fixed_width[j] = -cell->fixed_width[j] * maxwidth / 100; - - swidth = 0; - fwidth = 0; - nvar = 0; - for (i = bcol; i < ecol; i++) { - if (fixed[i]) { - fwidth += newwidth[i]; - } - else { - swidth += newwidth[i]; - nvar++; - } - } - width = max(cell->fixed_width[j], cell->minimum_width[j]) - - (cell->colspan[j] - 1) * t->cellspacing; - if (nvar > 0 && width > fwidth + swidth) { - s = 0.; - for (i = bcol; i < ecol; i++) { - if (!fixed[i]) - s += weight3(t->tabwidth[i]); - } - for (i = bcol; i < ecol; i++) { - if (!fixed[i]) - dwidth[i] = (width - fwidth) * weight3(t->tabwidth[i]) / s; - else - dwidth[i] = (double) newwidth[i]; - } - dv2sv(dwidth, newwidth, cell->colspan[j]); - if (cell->fixed_width[j] > 0) { - for (i = bcol; i < ecol; i++) - fixed[i] = 1; - } - } - } - - do { - nvar = 0; - swidth = 0; - fwidth = 0; - for (i = 0; i <= t->maxcol; i++) { - if (fixed[i]) { - fwidth += newwidth[i]; - } - else { - swidth += newwidth[i]; - nvar++; - } - } - width = maxwidth - t->maxcol * t->cellspacing; - if (nvar == 0 || width <= fwidth + swidth) - break; - - s = 0.; - for (i = 0; i <= t->maxcol; i++) { - if (!fixed[i]) - s += weight3(t->tabwidth[i]); - } - for (i = 0; i <= t->maxcol; i++) { - if (!fixed[i]) - dwidth[i] = (width - fwidth) * weight3(t->tabwidth[i]) / s; - else - dwidth[i] = (double) newwidth[i]; - } - dv2sv(dwidth, newwidth, t->maxcol + 1); - - try_again = 0; - for (i = 0; i <= t->maxcol; i++) { - if (!fixed[i]) { - if (newwidth[i] > t->tabwidth[i]) { - newwidth[i] = t->tabwidth[i]; - fixed[i] = 1; - try_again = 1; - } - else if (newwidth[i] < t->minimum_width[i]) { - newwidth[i] = t->minimum_width[i]; - fixed[i] = 1; - try_again = 1; - } - } - } - } while (try_again); -} -#endif /* not MATRIX */ - -void -check_table_height(struct table *t) -{ - int i, j, k; - struct { - short row[MAXCELL]; - short rowspan[MAXCELL]; - char index[MAXCELL]; - short maxcell; - short height[MAXCELL]; - } cell; - int space; - - cell.maxcell = -1; - - for (j = 0; j <= t->maxrow; j++) { - if (!t->tabattr[j]) - continue; - for (i = 0; i <= t->maxcol; i++) { - int t_dep, rowspan; - if (t->tabattr[j][i] & (HTT_X | HTT_Y)) - continue; - - if (t->tabdata[j][i] == NULL) - t_dep = 0; - else - t_dep = t->tabdata[j][i]->nitem; - - rowspan = table_rowspan(t, j, i); - if (rowspan > 1) { - int c = cell.maxcell + 1; - k = dsort_index(rowspan, cell.rowspan, - j, cell.row, t->maxrow + 1, - cell.index, c); - if (k <= cell.maxcell) { - int idx = cell.index[k]; - if (cell.row[idx] == j && - cell.rowspan[idx] == rowspan) - c = idx; - } - if (c > cell.maxcell && c < MAXCELL) { - cell.maxcell++; - cell.row[cell.maxcell] = j; - cell.rowspan[cell.maxcell] = rowspan; - cell.height[cell.maxcell] = 0; - if (cell.maxcell > k) - bcopy(cell.index + k, cell.index + k + 1, cell.maxcell - k); - cell.index[k] = cell.maxcell; - } - if (c <= cell.maxcell && c >= 0 && - cell.height[c] < t_dep) { - cell.height[c] = t_dep; - continue; - } - } - if (t->tabheight[j] < t_dep) - t->tabheight[j] = t_dep; - } - } - - switch (t->border_mode) { - case BORDER_THIN: - case BORDER_THICK: - case BORDER_NOWIN: - space = 1; - break; - case BORDER_NONE: - space = 0; - } - check_cell_width(t->tabheight, cell.height, cell.row, cell.rowspan, - cell.maxcell, cell.index, space, 1); -} - -int -get_table_width(struct table *t, short *orgwidth, short *cellwidth, - int check_minimum) -{ -#ifdef __GNUC__ - short newwidth[t->maxcol + 1]; -#else /* not __GNUC__ */ - short newwidth[MAXCOL]; -#endif /* not __GNUC__ */ - int i; - int swidth; - struct table_cell *cell = &t->cell; - - for (i = 0; i <= t->maxcol; i++) - newwidth[i] = max(orgwidth[i], 0); - - check_cell_width(newwidth, cellwidth, cell->col, cell->colspan, - cell->maxcell, cell->index, t->cellspacing, 0); - if (check_minimum) - check_minimum_width(t, newwidth); - - swidth = 0; - for (i = 0; i <= t->maxcol; i++) { - swidth += newwidth[i]; - } - swidth += table_border_width(t); - return swidth; -} - -#define minimum_table_width(t)\ -(get_table_width(t,t->minimum_width,t->cell.minimum_width,0)) -#define maximum_table_width(t)\ - (get_table_width(t,t->tabwidth,t->cell.width,0)) -#define fixed_table_width(t)\ - (get_table_width(t,t->fixed_width,t->cell.fixed_width,1)) - -void -renderCoTable(struct table *tbl) -{ - struct readbuffer obuf; - struct html_feed_environ h_env; - struct environment envs[MAX_ENV_LEVEL]; - struct table *t; - int i, j, col, row, b_width; - int width, nwidth, indent, maxwidth; -#ifdef __GNUC__ - short newwidth[tbl->maxcol + 1]; -#else /* not __GNUC__ */ - short newwidth[MAXCOL]; -#endif /* not __GNUC__ */ - - for (i = 0; i <= tbl->maxcol; i++) - newwidth[i] = tbl->tabwidth[i]; - - for (i = 0; i < tbl->ntable; i++) { - t = tbl->tables[i].ptr; - col = tbl->tables[i].col; - row = tbl->tables[i].row; - indent = tbl->tables[i].indent; - - init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL, tbl->tables[i].buf, - tbl->tabwidth[col], indent); - nwidth = newwidth[col]; - check_row(tbl, row); - b_width = 0; - for (j = col + 1; j <= tbl->maxcol; j++) { - if (tbl->tabattr[row][j] & HTT_X) { - h_env.limit += tbl->tabwidth[j]; - nwidth += newwidth[j]; - b_width += tbl->cellspacing; - } - else - break; - } - h_env.limit += b_width; -#ifndef TABLE_EXPAND - if (t->total_width == 0) - maxwidth = h_env.limit - indent; - else if (t->total_width > 0) - maxwidth = t->total_width; - else - maxwidth = t->total_width = -t->total_width * - get_spec_cell_width(tbl, row, col) / 100; -#else - maxwidth = h_env.limit - indent; - if (t->total_width > 0) { - double r = ((double) maxwidth) / t->total_width; - struct table_cell *cell = &t->cell; - - for (j = 0; j <= t->maxcol; j++) { - if (t->fixed_width[j] > 0) - t->fixed_width[j] = (int) (r * t->fixed_width[j]); - } - for (j = 0; j <= cell->maxcell; j++) { - if (cell->fixed_width[j] > 0) - cell->fixed_width[j] = (int) (r * cell->fixed_width[j]); - } - t->total_width = maxwidth; - } -#endif /* TABLE_EXPAND */ - renderTable(t, maxwidth, &h_env); - width = t->total_width - b_width + indent; - if (width > nwidth) { - int cell = tbl->tables[i].cell; - if (cell < 0) { - newwidth[col] = width; - } - else { - int ecol = col + tbl->cell.colspan[cell]; - int w = (width - nwidth) / tbl->cell.colspan[cell]; - int r = (width - nwidth) % tbl->cell.colspan[cell]; - for (j = col; j < ecol; j++) - newwidth[j] += w; - for (j = 1; j <= r; j++) - newwidth[ecol - j]++; - } - } - t = NULL; - } - for (i = 0; i <= tbl->maxcol; i++) - tbl->tabwidth[i] = newwidth[i]; -} - -static void -make_caption(struct table *t, struct html_feed_environ *h_env) -{ - struct html_feed_environ henv; - struct readbuffer obuf; - struct environment envs[MAX_ENV_LEVEL]; - TextList *tl; - Str tmp; - - if (t->caption->length <= 0) - return; - - if (t->total_width <= 0) - t->total_width = h_env->limit; - - init_henv(&henv, &obuf, envs, MAX_ENV_LEVEL, newTextList(), t->total_width, - h_env->envs[h_env->envc].indent); - HTMLlineproc1("<center>", &henv); - HTMLlineproc1(t->caption->ptr, &henv); - HTMLlineproc1("</center>", &henv); - - tl = henv.buf; - - if (tl->nitem > 0) { - TextListItem *ti; - tmp = Strnew_charp("<pre for_table>"); - for (ti = tl->first; ti != NULL; ti = ti->next) { - Strcat_charp(tmp, ti->ptr); - Strcat_char(tmp, '\n'); - } - Strcat_charp(tmp, "</pre>"); - HTMLlineproc1(tmp->ptr, h_env); - } -} - -void -renderTable(struct table *t, - int max_width, - struct html_feed_environ *h_env) -{ - int i, j, w, r, h; - Str renderbuf = Strnew(); - short new_tabwidth[MAXCOL]; -#ifdef MATRIX - int itr; - VEC *newwidth; - MAT *mat, *minv; - PERM *pivot; -#endif /* MATRIX */ - int maxheight = 0; - Str vrulea, vruleb, vrulec; -#ifdef ID_EXT - Str idtag; -#endif /* ID_EXT */ - - if (t->maxcol < 0) { - make_caption(t, h_env); - return; - } - - max_width -= table_border_width(t); - - if (max_width <= 0) - max_width = 1; - - check_maximum_width(t); - -#ifdef MATRIX - if (t->maxcol == 0) { - if (t->tabwidth[0] > max_width) - t->tabwidth[0] = max_width; - if (t->total_width > 0) - t->tabwidth[0] = max_width; - else if (t->fixed_width[0] > 0) - t->tabwidth[0] = t->fixed_width[0]; - if (t->tabwidth[0] < t->minimum_width[0]) - t->tabwidth[0] = t->minimum_width[0]; - } - else { - set_table_matrix(t, max_width); - - itr = 0; - mat = m_get(t->maxcol + 1, t->maxcol + 1); - pivot = px_get(t->maxcol + 1); - newwidth = v_get(t->maxcol + 1); - minv = m_get(t->maxcol + 1, t->maxcol + 1); - do { - m_copy(t->matrix, mat); - LUfactor(mat, pivot); - LUsolve(mat, pivot, t->vector, newwidth); - dv2sv(newwidth->ve, new_tabwidth, t->maxcol + 1); - LUinverse(mat, pivot, minv); -#ifdef TABLE_DEBUG - fprintf(stderr, "max_width=%d\n", max_width); - fprintf(stderr, "minimum : "); - for (i = 0; i <= t->maxcol; i++) - fprintf(stderr, "%2d ", t->minimum_width[i]); - fprintf(stderr, "\ndecided : "); - for (i = 0; i <= t->maxcol; i++) - fprintf(stderr, "%2d ", new_tabwidth[i]); - fprintf(stderr, "\n"); -#endif /* TABLE_DEBUG */ - itr++; - - } while (check_table_width(t, new_tabwidth, minv, itr)); - v_free(newwidth); - px_free(pivot); - m_free(mat); - m_free(minv); - m_free(t->matrix); - v_free(t->vector); - for (i = 0; i <= t->maxcol; i++) { - t->tabwidth[i] = new_tabwidth[i]; - } - } -#else /* not MATRIX */ - set_table_width(t, new_tabwidth, max_width); - for (i = 0; i <= t->maxcol; i++) { - t->tabwidth[i] = new_tabwidth[i]; - } -#endif /* not MATRIX */ - - renderCoTable(t); - check_minimum_width(t, t->tabwidth); - - t->total_width = 0; - for (i = 0; i <= t->maxcol; i++) { - if (t->border_mode != BORDER_NONE && t->tabwidth[i] % RULE_WIDTH == 1) - t->tabwidth[i]++; - t->total_width += t->tabwidth[i]; - } - - t->total_width += table_border_width(t); - - for (i = 0; i <= t->maxcol; i++) { - for (j = 0; j <= t->maxrow; j++) { - check_row(t, j); - if (t->tabattr[j][i] & HTT_Y) - continue; - do_refill(t, j, i); - } - } - - check_table_height(t); - - /* table output */ - make_caption(t, h_env); - - HTMLlineproc1("<pre for_table>", h_env); -#ifdef ID_EXT - if (t->id != NULL) { - idtag = Sprintf("<_id id=\"%s\">", (t->id)->ptr); - HTMLlineproc1(idtag->ptr, h_env); - } -#endif /* ID_EXT */ - switch (t->border_mode) { - case BORDER_THIN: - case BORDER_THICK: - renderbuf = Strnew(); - print_sep(t, -1, T_TOP, t->maxcol, renderbuf); - HTMLlineproc1(renderbuf->ptr, h_env); - maxheight += 1; - break; - } - vruleb = Strnew(); - switch (t->border_mode) { - case BORDER_THIN: - case BORDER_THICK: - vrulea = Strnew(); - vrulec = Strnew(); - Strcat_charp(vrulea, TK_VERTICALBAR(t->border_mode)); - for (i = 0; i < t->cellpadding; i++) { - Strcat_char(vrulea, ' '); - Strcat_char(vruleb, ' '); - Strcat_char(vrulec, ' '); - } - Strcat_charp(vrulec, TK_VERTICALBAR(t->border_mode)); - case BORDER_NOWIN: -#if defined(__EMX__)&&!defined(JP_CHARSET) - Strcat_charp(vruleb, CodePage==850?"³":TN_VERTICALBAR); -#else - Strcat_charp(vruleb, TN_VERTICALBAR); -#endif - for (i = 0; i < t->cellpadding; i++) - Strcat_char(vruleb, ' '); - break; - case BORDER_NONE: - for (i = 0; i < t->cellspacing; i++) - Strcat_char(vruleb, ' '); - } - - for (r = 0; r <= t->maxrow; r++) { - for (h = 0; h < t->tabheight[r]; h++) { - renderbuf = Strnew(); - if (t->border_mode == BORDER_THIN || t->border_mode == BORDER_THICK) - Strcat(renderbuf, vrulea); -#ifdef ID_EXT - if (t->tridvalue[r] != NULL && h == 0) { - idtag = Sprintf("<_id id=\"%s\">", (t->tridvalue[r])->ptr); - Strcat(renderbuf, idtag); - } -#endif /* ID_EXT */ - for (i = 0; i <= t->maxcol; i++) { - check_row(t, r); -#ifdef ID_EXT - if (t->tabidvalue[r][i] != NULL && h == 0) { - idtag = Sprintf("<_id id=\"%s\">", (t->tabidvalue[r][i])->ptr); - Strcat(renderbuf, idtag); - } -#endif /* ID_EXT */ - if (!(t->tabattr[r][i] & HTT_X)) { - w = t->tabwidth[i]; - for (j = i + 1; - j <= t->maxcol && (t->tabattr[r][j] & HTT_X); - j++) - w += t->tabwidth[j] + t->cellspacing; - if (t->tabattr[r][i] & HTT_Y) { - for (j = r - 1; - j >= 0 && t->tabattr[j] && (t->tabattr[j][i] & HTT_Y); - j--); - print_item(t, j, i, w, renderbuf); - } - else - print_item(t, r, i, w, renderbuf); - } - if (i < t->maxcol && !(t->tabattr[r][i + 1] & HTT_X)) - Strcat(renderbuf, vruleb); - } - switch (t->border_mode) { - case BORDER_THIN: - case BORDER_THICK: - Strcat(renderbuf, vrulec); - Strcat_charp(renderbuf, "<eol>"); - maxheight += 1; - break; - case BORDER_NONE: - case BORDER_NOWIN: - Strcat_charp(renderbuf, "<eol>"); - break; - } - HTMLlineproc1(renderbuf->ptr, h_env); - } - if (r < t->maxrow && t->border_mode != BORDER_NONE) { - renderbuf = Strnew(); - print_sep(t, r, T_MIDDLE, t->maxcol, renderbuf); - HTMLlineproc1(renderbuf->ptr, h_env); - } - maxheight += t->tabheight[r]; - } - if (t->border_mode == BORDER_THIN || t->border_mode == BORDER_THICK) { - renderbuf = Strnew(); - print_sep(t, t->maxrow, T_BOTTOM, t->maxcol, renderbuf); - HTMLlineproc1(renderbuf->ptr, h_env); - maxheight += 1; - } - if (maxheight == 0) - HTMLlineproc1(" <eol>", h_env); - HTMLlineproc1("</pre>", h_env); -} - - -struct table * -begin_table(int border, int spacing, int padding) -{ - struct table *t; - int mincell = minimum_cellspacing(border); - - t = newTable(); - t->row = t->col = -1; - t->maxcol = -1; - t->maxrow = -1; - t->border_mode = border; - t->flag = 0; - if (border == BORDER_NOWIN) - t->flag |= TBL_EXPAND_OK; - t->cellspacing = max(spacing, mincell); - switch (border) { - case BORDER_THIN: - case BORDER_THICK: - case BORDER_NOWIN: - t->cellpadding = (t->cellspacing - mincell) / 2; - break; - case BORDER_NONE: - t->cellpadding = t->cellspacing - mincell; - } - - if (padding > t->cellpadding) - t->cellpadding = padding; - - switch (border) { - case BORDER_THIN: - case BORDER_THICK: - case BORDER_NOWIN: - t->cellspacing = 2 * t->cellpadding + mincell; - break; - case BORDER_NONE: - t->cellspacing = t->cellpadding + mincell; - } - return t; -} - -static void -check_minimum0(struct table *t, int min) -{ - int i, w, ww; - struct table_cell *cell; - - if (t->col < 0) - return; - if (t->tabwidth[t->col] < 0) - return; - check_row(t, t->row); - w = table_colspan(t, t->row, t->col); - min += t->indent; - if (w == 1) - ww = min; - else { - cell = &t->cell; - ww = 0; - if (cell->icell >= 0 && cell->minimum_width[cell->icell] < min) - cell->minimum_width[cell->icell] = min; - } - for (i = t->col; - i <= t->maxcol && (i == t->col || (t->tabattr[t->row][i] & HTT_X)); - i++) { - if (t->minimum_width[i] < ww) - t->minimum_width[i] = ww; - } -} - -static int -setwidth0(struct table *t, struct table_mode *mode) -{ - int w; - int width = t->tabcontentssize; - struct table_cell *cell = &t->cell; - - if (t->col < 0) - return -1; - if (t->tabwidth[t->col] < 0) - return -1; - check_row(t, t->row); - if (t->linfo.prev_spaces > 0) - width -= t->linfo.prev_spaces; - w = table_colspan(t, t->row, t->col); - if (w == 1) { - if (t->tabwidth[t->col] < width) - t->tabwidth[t->col] = width; - } - else if (cell->icell >= 0) { - if (cell->width[cell->icell] < width) - cell->width[cell->icell] = width; - } - return width; -} - -static void -setwidth(struct table *t, struct table_mode *mode) -{ - int width = setwidth0(t, mode); - if (width < 0) - return; -#ifdef NOWRAP - if (t->tabattr[t->row][t->col] & HTT_NOWRAP) - check_minimum0(t, width); -#endif /* NOWRAP */ - if (mode->pre_mode & (TBLM_NOBR | TBLM_PRE | TBLM_PRE_INT) && - mode->nobr_offset >= 0) - check_minimum0(t, width - mode->nobr_offset); -} - -static void -addcontentssize(struct table *t, int width) -{ - - if (t->col < 0) - return; - if (t->tabwidth[t->col] < 0) - return; - check_row(t, t->row); - t->tabcontentssize += width; -} - -static void -clearcontentssize(struct table *t, struct table_mode *mode) -{ - mode->nobr_offset = 0; - t->linfo.prev_spaces = -1; - t->linfo.prevchar = ' '; - t->tabcontentssize = 0; -} - -void -check_rowcol(struct table *tbl) -{ - if (!(tbl->flag & TBL_IN_ROW)) { - tbl->flag |= TBL_IN_ROW; - tbl->row++; - if (tbl->row > tbl->maxrow) - tbl->maxrow = tbl->row; - tbl->col = -1; - } - if (tbl->row == -1) - tbl->row = 0; - if (tbl->col == -1) - tbl->col = 0; - - for (;; tbl->row++) { - check_row(tbl, tbl->row); - for (; tbl->col < MAXCOL && - tbl->tabattr[tbl->row][tbl->col] & (HTT_X | HTT_Y); - tbl->col++); - if (tbl->col < MAXCOL) - break; - tbl->col = 0; - } - if (tbl->row > tbl->maxrow) - tbl->maxrow = tbl->row; - if (tbl->col > tbl->maxcol) - tbl->maxcol = tbl->col; - - tbl->flag |= TBL_IN_COL; -} - -int -skip_space(struct table *t, char *line, struct table_linfo *linfo, - int checkminimum) -{ - int skip = 0, s = linfo->prev_spaces; - Lineprop ctype = linfo->prev_ctype, prev_ctype; - char prevchar = linfo->prevchar; - int w = (linfo->prev_spaces == -1) ? 0 : linfo->length; - int min = 1; - - if (*line == '<' && line[strlen(line) - 1] == '>') { - if (checkminimum) - check_minimum0(t, visible_length(line)); - return 0; - } - - while (*line) { - char c = *line, *save = line; - int ec = '\0', len = 1, wlen = 1; - prev_ctype = ctype; - ctype = get_ctype(c, prev_ctype); - if (min < w) - min = w; - if (ctype == PC_ASCII && IS_SPACE(c)) { - w = 0; - s++; - } - else { - if (c == '&') { - ec = getescapechar(&line); - if (ec) { - c = ec; - if (IS_CNTRL(ec)) - ctype = PC_CTRL; - else - ctype = PC_ASCII; - len = strlen(conv_latin1(ec)); - wlen = line - save; - } - } - if (prevchar && is_boundary(prevchar, prev_ctype, c, ctype)) { - w = len; - } - else { - w += len; - } - if (s > 0) { -#ifdef JP_CHARSET - if (ctype == PC_KANJI1 && prev_ctype == PC_KANJI2) - skip += s; - else -#endif /* JP_CHARSET */ - skip += s - 1; - } - s = 0; - } - prevchar = c; - line = save + wlen; - } - if (s > 1) { - skip += s - 1; - linfo->prev_spaces = 1; - } - else { - linfo->prev_spaces = s; - } - linfo->prev_ctype = ctype; - linfo->prevchar = prevchar; - - if (checkminimum) { - if (min < w) - min = w; - linfo->length = w; - check_minimum0(t, min); - } - return skip; -} - -#define TAG_ACTION_NONE 0 -#define TAG_ACTION_FEED 1 -#define TAG_ACTION_TABLE 2 -#define TAG_ACTION_N_TABLE 3 - -static int -feed_table_tag(struct table *tbl, char *line, struct table_mode *mode, int width) -{ - int cmd; - char *s_line; - struct table_cell *cell = &tbl->cell; - struct parsed_tagarg *t_arg, *t; - int colspan, rowspan; - int col, prev_col; - int i, j, k, v, v0, w, id, status; - Str tok, tmp, anchor; - table_attr align; - - s_line = line; - cmd = gethtmlcmd(&s_line, &status); - - if (mode->pre_mode & TBLM_IGNORE) { - switch (cmd) { - case HTML_N_STYLE: - mode->pre_mode &= ~TBLM_STYLE; - case HTML_N_SCRIPT: - mode->pre_mode &= ~TBLM_SCRIPT; - default: - return TAG_ACTION_NONE; - } - } - -#ifdef MENU_SELECT - /* failsafe: a tag other than <option></option>and </select> in * - * <select> environment is regarded as the end of <select>. */ - if (mode->pre_mode & TBLM_INSELECT) { - switch (cmd) { - case HTML_TABLE: - case HTML_N_TABLE: - case HTML_TR: - case HTML_N_TR: - case HTML_TD: - case HTML_N_TD: - case HTML_TH: - case HTML_N_TH: - case HTML_THEAD: - case HTML_N_THEAD: - case HTML_TBODY: - case HTML_N_TBODY: - case HTML_TFOOT: - case HTML_N_TFOOT: - case HTML_COLGROUP: - case HTML_N_COLGROUP: - case HTML_COL: - mode->pre_mode &= ~TBLM_INSELECT; - tmp = process_n_select(); - feed_table1(tbl, tmp, mode, width); - } - } -#endif /* MENU_SELECT */ - - switch (cmd) { - case HTML_TABLE: - return TAG_ACTION_TABLE; - case HTML_N_TABLE: - return TAG_ACTION_N_TABLE; - case HTML_TR: - if (tbl->col >= 0 && tbl->tabcontentssize > 0) - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - mode->caption = 0; - mode->indent_level = 0; - mode->nobr_level = 0; - mode->mode_level = 0; - mode->pre_mode = 0; - tbl->col = -1; - tbl->row++; - tbl->flag |= TBL_IN_ROW; - tbl->indent = 0; - align = 0; - t_arg = parse_tag(line + 3); - for (t = t_arg; t; t = t->next) { - if (!strcasecmp(t->arg, "align") && t->value) { - if (!strcasecmp(t->value, "left")) - align = (HTT_LEFT | HTT_TRSET); - else if (!strcasecmp(t->value, "right")) - align = (HTT_RIGHT | HTT_TRSET); - else if (!strcasecmp(t->value, "center")) - align = (HTT_CENTER | HTT_TRSET); - } -#ifdef ID_EXT - if (!strcasecmp(t->arg, "id") && t->value) { - tbl->tridvalue[tbl->row] = Strnew_charp(t->value); - } -#endif /* ID_EXT */ - } - tbl->trattr = align; - break; - case HTML_TH: - case HTML_TD: - prev_col = tbl->col; - if (tbl->col >= 0 && tbl->tabcontentssize > 0) - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - mode->caption = 0; - mode->indent_level = 0; - mode->nobr_level = 0; - mode->mode_level = 0; - mode->pre_mode = 0; - tbl->flag |= TBL_IN_COL; - tbl->linfo.prev_spaces = -1; - tbl->linfo.prevchar = ' '; - tbl->linfo.prev_ctype = PC_ASCII; - tbl->indent = 0; - if (tbl->row == -1) { - /* for broken HTML... */ - tbl->row = -1; - tbl->col = -1; - tbl->maxrow = tbl->row; - } - if (tbl->col == -1) { - if (!(tbl->flag & TBL_IN_ROW)) { - tbl->row++; - tbl->flag |= TBL_IN_ROW; - } - if (tbl->row > tbl->maxrow) - tbl->maxrow = tbl->row; - } - tbl->col++; - check_row(tbl, tbl->row); - while (tbl->tabattr[tbl->row][tbl->col]) { - tbl->col++; - } - if (tbl->col > MAXCOL - 1) { - tbl->col = prev_col; - return TAG_ACTION_NONE; - } - if (tbl->col > tbl->maxcol) { - tbl->maxcol = tbl->col; - } - tbl->height = 0; - t_arg = parse_tag(line + 3); - colspan = rowspan = 1; - v = 0; - if (tbl->trattr & HTT_TRSET) - align = (tbl->trattr & HTT_ALIGN); - else if (cmd == HTML_TH) - align = HTT_CENTER; - else - align = HTT_LEFT; - for (t = t_arg; t; t = t->next) { - if (!strcasecmp(t->arg, "rowspan") && t->value) { - rowspan = atoi(t->value); - if ((tbl->row + rowspan) >= tbl->max_rowsize) - check_row(tbl, tbl->row + rowspan); - } - else if (!strcasecmp(t->arg, "colspan") && t->value) { - colspan = atoi(t->value); - if ((tbl->col + colspan) >= MAXCOL) { - /* Can't expand column */ - colspan = MAXCOL - tbl->col; - } - } - else if (!strcasecmp(t->arg, "align") && t->value) { - if (!strcasecmp(t->value, "left")) - align = HTT_LEFT; - else if (!strcasecmp(t->value, "right")) - align = HTT_RIGHT; - else if (!strcasecmp(t->value, "center")) - align = HTT_CENTER; - } -#ifdef NOWRAP - else if (!strcasecmp(t->arg, "nowrap")) - tbl->tabattr[tbl->row][tbl->col] |= HTT_NOWRAP; -#endif /* NOWRAP */ - else if (!strcasecmp(t->arg, "width") && t->value) { - if (IS_DIGIT(*t->value)) { - v = atoi(t->value); - if (v == 0) - v = 1; - else if (v < 0) - v = 0; - if (t->value[strlen(t->value) - 1] == '%') { - v = -v; - } - else { -#ifdef TABLE_EXPAND - v = max(v / tbl->ppc, 1); -#else /* not TABLE_EXPAND */ - v = v / PIXEL_PER_CHAR; -#endif /* not TABLE_EXPAND */ - } - } - else - continue; -#ifdef ID_EXT - } - else if (!strcasecmp(t->arg, "id") && t->value) { - tbl->tabidvalue[tbl->row][tbl->col] = Strnew_charp(t->value); -#endif /* ID_EXT */ - } - } -#ifdef NOWRAP - if (v != 0) { - /* NOWRAP and WIDTH= conflicts each other */ - tbl->tabattr[tbl->row][tbl->col] &= ~HTT_NOWRAP; - } -#endif /* NOWRAP */ - tbl->tabattr[tbl->row][tbl->col] &= ~HTT_ALIGN; - tbl->tabattr[tbl->row][tbl->col] |= align; - if (colspan > 1) { - col = tbl->col; - - cell->icell = cell->maxcell + 1; - k = dsort_index(colspan, cell->colspan, col, cell->col, MAXCOL, - cell->index, cell->icell); - if (k <= cell->maxcell) { - i = cell->index[k]; - if (cell->col[i] == col && - cell->colspan[i] == colspan) - cell->icell = i; - } - if (cell->icell > cell->maxcell && cell->icell < MAXCELL) { - cell->maxcell++; - cell->col[cell->maxcell] = col; - cell->colspan[cell->maxcell] = colspan; - cell->width[cell->maxcell] = 0; - cell->minimum_width[cell->maxcell] = 0; - cell->fixed_width[cell->maxcell] = 0; - if (cell->maxcell > k) - bcopy(cell->index + k, cell->index + k + 1, cell->maxcell - k); - cell->index[k] = cell->maxcell; - } - if (cell->icell > cell->maxcell) - cell->icell = -1; - } - if (v != 0) { - if (colspan == 1) { - v0 = tbl->fixed_width[tbl->col]; - if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0)) { -#ifdef TABLE_DEBUG - fprintf(stderr, "width(%d) = %d\n", tbl->col, v); -#endif /* TABLE_DEBUG */ - tbl->fixed_width[tbl->col] = v; - } - } - else if (cell->icell >= 0) { - v0 = cell->fixed_width[cell->icell]; - if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0)) - cell->fixed_width[cell->icell] = v; - } - } - for (i = 0; i < rowspan; i++) { - check_row(tbl, tbl->row + i); - for (j = 0; j < colspan; j++) { - tbl->tabattr[tbl->row + i][tbl->col + j] &= ~(HTT_X | HTT_Y); - tbl->tabattr[tbl->row + i][tbl->col + j] |= - ((i > 0) ? HTT_Y : 0) | ((j > 0) ? HTT_X : 0); - if (tbl->col + j > tbl->maxcol) { - tbl->maxcol = tbl->col + j; - } - } - if (tbl->row + i > tbl->maxrow) { - tbl->maxrow = tbl->row + i; - } - } - break; - case HTML_N_TR: - setwidth(tbl, mode); - tbl->col = -1; - tbl->flag &= ~(TBL_IN_ROW | TBL_IN_COL); - return TAG_ACTION_NONE; - case HTML_N_TH: - case HTML_N_TD: - setwidth(tbl, mode); - tbl->flag &= ~TBL_IN_COL; -#ifdef TABLE_DEBUG - { - TextListItem *it; - int i = tbl->col, j = tbl->row; - fprintf(stderr, "(a) row,col: %d, %d\n", j, i); - if (tbl->tabdata[j] && tbl->tabdata[j][i]) { - for (it = tbl->tabdata[j][i]->first; it; it = it->next) - fprintf(stderr, " [%s] \n", it->ptr); - } - } -#endif - return TAG_ACTION_NONE; - case HTML_P: - case HTML_BR: - case HTML_DT: - case HTML_DD: - case HTML_CENTER: - case HTML_N_CENTER: - case HTML_DIV: - case HTML_N_DIV: - case HTML_H: - case HTML_N_H: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - if (cmd == HTML_DD) - addcontentssize(tbl, tbl->indent); - break; - case HTML_DL: - case HTML_BLQ: - case HTML_OL: - case HTML_UL: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - mode->indent_level++; - if (mode->indent_level <= MAX_INDENT_LEVEL) - tbl->indent += INDENT_INCR; - if (cmd == HTML_BLQ) { - check_minimum0(tbl, 0); - addcontentssize(tbl, tbl->indent); - } - break; - case HTML_N_DL: - case HTML_N_BLQ: - case HTML_N_OL: - case HTML_N_UL: - if (mode->indent_level > 0) { - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - mode->indent_level--; - if (mode->indent_level < MAX_INDENT_LEVEL) - tbl->indent -= INDENT_INCR; - } - break; - case HTML_LI: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - check_minimum0(tbl, 0); - addcontentssize(tbl, tbl->indent); - break; - case HTML_PRE: - case HTML_LISTING: - case HTML_XMP: - setwidth(tbl, mode); - check_rowcol(tbl); - clearcontentssize(tbl, mode); - pushdata(tbl, tbl->row, tbl->col, line); - mode->pre_mode |= TBLM_PRE; - mode->mode_level++; - break; - case HTML_N_PRE: - case HTML_N_LISTING: - case HTML_N_XMP: - setwidth(tbl, mode); - check_rowcol(tbl); - clearcontentssize(tbl, mode); - pushdata(tbl, tbl->row, tbl->col, line); - if (mode->mode_level > 0) - mode->mode_level--; - if (mode->mode_level == 0) - mode->pre_mode &= ~TBLM_PRE; - tbl->linfo.prev_spaces = 0; - tbl->linfo.prevchar = '\0'; - tbl->linfo.prev_ctype = PC_ASCII; - break; - case HTML_NOBR: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - if (!(mode->pre_mode & TBLM_NOBR)) { - mode->nobr_offset = -1; - mode->pre_mode |= TBLM_NOBR; - } - mode->nobr_level++; - break; - case HTML_WBR: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - mode->nobr_offset = -1; - break; - case HTML_N_NOBR: - if (mode->nobr_level > 0) - mode->nobr_level--; - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - if (mode->nobr_level == 0) - mode->pre_mode &= ~TBLM_NOBR; - break; - case HTML_PRE_INT: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - if (!(mode->pre_mode & TBLM_PRE_INT)) { - mode->nobr_offset = -1; - mode->pre_mode |= TBLM_PRE_INT; - } - tbl->linfo.prev_spaces = 0; - break; - case HTML_N_PRE_INT: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - mode->pre_mode &= ~TBLM_PRE_INT; - break; - case HTML_IMG: - tok = process_img(parse_tag(line + 3)); - feed_table1(tbl, tok, mode, width); - break; -#ifdef NEW_FORM - case HTML_FORM: - process_form(parse_tag(line)); - break; - case HTML_N_FORM: - process_n_form(); - break; -#else /* not NEW_FORM */ - case HTML_FORM: - case HTML_N_FORM: - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, "<br>"); - setwidth(tbl, mode); - clearcontentssize(tbl, mode); - if (line[1] == '/') { - tok = Strnew_charp("</form_int "); - Strcat_charp(tok, line + 6); - } - else { - tok = Strnew_charp("<form_int "); - Strcat_charp(tok, line + 5); - } - pushdata(tbl, tbl->row, tbl->col, tok->ptr); - break; -#endif /* not NEW_FORM */ - case HTML_INPUT: - tmp = process_input(parse_tag(line + 6)); - feed_table1(tbl, tmp, mode, width); - break; - case HTML_SELECT: - t_arg = parse_tag(line + 7); - tmp = process_select(t_arg); - feed_table1(tbl, tmp, mode, width); -#ifdef MENU_SELECT - if (!tag_exists(t_arg, "multiple")) /* non-multiple select */ - mode->pre_mode |= TBLM_INSELECT; -#endif /* MENU_SELECT */ - break; - case HTML_N_SELECT: -#ifdef MENU_SELECT - mode->pre_mode &= ~TBLM_INSELECT; -#endif /* MENU_SELECT */ - tmp = process_n_select(); - feed_table1(tbl, tmp, mode, width); - break; - case HTML_OPTION: - tmp = process_option(parse_tag(line + 7)); - if (tmp) - feed_table1(tbl, tmp, mode, width); -#ifdef MENU_SELECT - else - feed_select(line); -#endif /* MENU_SELECT */ - break; - case HTML_TEXTAREA: - w = 0; - check_rowcol(tbl); - if (tbl->col + 1 <= tbl->maxcol && - tbl->tabattr[tbl->row][tbl->col + 1] & HTT_X) { - if (cell->icell >= 0 && cell->fixed_width[cell->icell] > 0) - w = cell->fixed_width[cell->icell]; - } - else { - if (tbl->fixed_width[tbl->col] > 0) - w = tbl->fixed_width[tbl->col]; - } - tmp = process_textarea(parse_tag(line + 9), w); - feed_table1(tbl, tmp, mode, width); - mode->pre_mode |= TBLM_INTXTA; - break; - case HTML_N_TEXTAREA: - mode->pre_mode &= ~TBLM_INTXTA; - tmp = process_n_textarea(); - feed_table1(tbl, tmp, mode, width); - break; - case HTML_A: - anchor = NULL; - check_rowcol(tbl); - t_arg = parse_tag(line + 2); - i = 0; - for (t = t_arg; t; t = t->next) { - if (strcasecmp(t->arg, "href") == 0 && t->value) { - anchor = Strnew_charp(t->value); - } - else if (strcasecmp(t->arg, "hseq") == 0 && t->value) { - i = atoi(t->value); - } - } - if (i == 0 && anchor) { - Str tmp = process_anchor(line); - pushdata(tbl, tbl->row, tbl->col, tmp->ptr); - if (mode->pre_mode & (TBLM_PRE | TBLM_NOBR)) - addcontentssize(tbl, 1); - else - check_minimum0(tbl, 1); - setwidth(tbl, mode); - } - else { - pushdata(tbl, tbl->row, tbl->col, line); - } - break; - case HTML_DEL: - case HTML_N_DEL: - case HTML_INS: - case HTML_N_INS: - pushdata(tbl, tbl->row, tbl->col, line); - i = 5; - check_minimum0(tbl, i); - addcontentssize(tbl, i); - setwidth(tbl, mode); - break; - case HTML_DUMMY_TABLE: - id = -1; - w = 0; - t_arg = parse_tag(line + 12); - for (t = t_arg; t; t = t->next) { - if (!strcasecmp(t->arg, "id") && t->value) { - id = atoi(t->value); - } - else if (!strcasecmp(t->arg, "width") && t->value) { - w = atoi(t->value); - } - } - if (id >= 0) { - setwidth(tbl, mode); - check_rowcol(tbl); - pushdata(tbl, tbl->row, tbl->col, line); - clearcontentssize(tbl, mode); - addcontentssize(tbl, maximum_table_width(tbl->tables[id].ptr)); - check_minimum0(tbl, minimum_table_width(tbl->tables[id].ptr)); - if (w > 0) - check_minimum0(tbl, w); - else - check_minimum0(tbl, fixed_table_width(tbl->tables[id].ptr)); - setwidth0(tbl, mode); - clearcontentssize(tbl, mode); - } - break; - case HTML_CAPTION: - mode->caption = 1; - break; - case HTML_N_CAPTION: - mode->caption = 0; - break; - case HTML_THEAD: - case HTML_N_THEAD: - case HTML_TBODY: - case HTML_N_TBODY: - case HTML_TFOOT: - case HTML_N_TFOOT: - case HTML_COLGROUP: - case HTML_N_COLGROUP: - case HTML_COL: - break; - case HTML_SCRIPT: - mode->pre_mode |= TBLM_SCRIPT; - break; - case HTML_STYLE: - mode->pre_mode |= TBLM_STYLE; - break; - default: - /* unknown tag: put into table */ - return TAG_ACTION_FEED; - } - return TAG_ACTION_NONE; -} - - -int -feed_table(struct table *tbl, char **tline, struct table_mode *mode, int width) -{ - int i; - char *line; - char *p; - Str tok, tmp; - struct table_linfo *linfo = &tbl->linfo; - - if (*tline == NULL || **tline == '\0') - return -1; - - tok = Strnew(); - if (tbl->suspended_input->length > 0) { - Strcat_charp(tbl->suspended_input, *tline); - *tline = tbl->suspended_input->ptr; - tbl->suspended_input = Strnew(); - tbl->status = R_ST_NORMAL; - } - while (read_token(tok, tline, &tbl->status, mode->pre_mode & TBLM_PREMODE, 0)) { - if (ST_IS_COMMENT(tbl->status)) { - continue; - } - else if (tbl->status != R_ST_NORMAL) { - /* line ended within tag */ - int l = tok->length; - if (tok->ptr[l - 1] == '\n') { - Strchop(tok); - if (ST_IS_REAL_TAG(tbl->status)) - Strcat_char(tok, ' '); - } - tbl->suspended_input = Strdup(tok); - return -1; - } - line = tok->ptr; - if (mode->caption && !TAG_IS(line, "</caption", 9)) { - Strcat(tbl->caption, tok); - continue; - } - if (*line == '<') { - int action = feed_table_tag(tbl, line, mode, width); - if (action == TAG_ACTION_NONE) - continue; - else if (action == TAG_ACTION_N_TABLE) - return 0; - else if (action == TAG_ACTION_TABLE) { - *tline -= tok->length; - return 1; - } - } - if (mode->pre_mode & TBLM_IGNORE) - continue; - if (mode->pre_mode & TBLM_INTXTA) { - feed_textarea(line); - continue; - } -#ifdef MENU_SELECT - if (mode->pre_mode & TBLM_INSELECT) { - feed_select(line); - continue; - } -#endif /* MENU_SELECT */ - /* convert &...; if it is latin-1 character */ - if (!(*line == '<' && line[strlen(line) - 1] == '>') && - strchr(line, '&') != NULL) { - tmp = Strnew(); - for (p = line; *p;) { - char *q, *r; - if (*p == '&') { - if (!strncasecmp(p, "&", 5) || - !strncasecmp(p, ">", 4) || - !strncasecmp(p, "<", 4)) { - /* do not convert */ - Strcat_char(tmp, *p); - p++; - } - else { - q = p; - r = getescapecmd(&p); - if (r != NULL && ((*r & 0x80) || IS_CNTRL(*r))) { - /* latin-1 character */ - Strcat_charp(tmp, r); - } - else { - Strcat_char(tmp, *q); - p = q + 1; - } - } - } - else { - Strcat_char(tmp, *p); - p++; - } - } - line = tmp->ptr; - } - if (!(mode->pre_mode & (TBLM_PRE | TBLM_PRE_INT))) { - if (!(tbl->flag & TBL_IN_COL)) { - linfo->prev_spaces = -1; - linfo->prev_ctype = PC_ASCII; - } - if (linfo->prev_spaces != 0) - while (IS_SPACE(*line)) - line++; - if (*line == '\0') - continue; - check_rowcol(tbl); - if (mode->pre_mode & TBLM_NOBR && mode->nobr_offset < 0) - mode->nobr_offset = tbl->tabcontentssize; - - /* count of number of spaces skipped in normal mode */ - i = skip_space(tbl, line, linfo, !(mode->pre_mode & TBLM_NOBR)); - addcontentssize(tbl, visible_length(line) - i); - setwidth(tbl, mode); - } - else { - /* <pre> mode or something like it */ - check_rowcol(tbl); - if (mode->pre_mode & TBLM_PRE_INT && mode->nobr_offset < 0) - mode->nobr_offset = tbl->tabcontentssize; - i = maximum_visible_length(line); - addcontentssize(tbl, i); - setwidth(tbl, mode); - if (!(mode->pre_mode & TBLM_PRE_INT)) { - p = line + strlen(line) - 1; - if (*p == '\r' || *p == '\n') - clearcontentssize(tbl, mode); - } - } - pushdata(tbl, tbl->row, tbl->col, line); - } - if (ST_IS_COMMENT(tbl->status)) - return 2; - else - return -1; -} - -void -feed_table1(struct table *tbl, Str tok, struct table_mode *mode, int width) -{ - char *p; - if (!tok) - return; - p = tok->ptr; - feed_table(tbl, &p, mode, width); -} - -void -pushTable(struct table *tbl, struct table *tbl1) -{ - int col; - int row; - - check_rowcol(tbl); - col = tbl->col; - row = tbl->row; - - if (tbl->ntable >= tbl->tables_size) { - struct table_in *tmp; - tbl->tables_size += MAX_TABLE_N; - tmp = New_N(struct table_in, tbl->tables_size); - if (tbl->tables) -#ifdef __CYGWIN__ - bcopy((const char *) tbl->tables, (char *) tmp, (size_t) tbl->ntable * sizeof(struct table_in)); -#else /* not __CYGWIN__ */ - bcopy(tbl->tables, tmp, tbl->ntable * sizeof(struct table_in)); -#endif /* not __CYGWIN__ */ - tbl->tables = tmp; - } - - tbl->tables[tbl->ntable].ptr = tbl1; - tbl->tables[tbl->ntable].col = col; - tbl->tables[tbl->ntable].row = row; - tbl->tables[tbl->ntable].indent = tbl->indent; - tbl->tables[tbl->ntable].buf = newTextList(); - check_row(tbl, row); - if (col + 1 <= tbl->maxcol && - tbl->tabattr[row][col + 1] & HTT_X) - tbl->tables[tbl->ntable].cell = tbl->cell.icell; - else - tbl->tables[tbl->ntable].cell = -1; - tbl->ntable++; -} - -#ifdef MATRIX -int -correct_table_matrix(struct table *t, int col, int cspan, int a, double b) -{ - int i, j; - int ecol = col + cspan; - double w = 1. / (b * b); - - for (i = col; i < ecol; i++) { - v_add_val(t->vector, i, w * a); - for (j = i; j < ecol; j++) { - m_add_val(t->matrix, i, j, w); - m_set_val(t->matrix, j, i, m_entry(t->matrix, i, j)); - } - } - return i; -} - -static void -correct_table_matrix2(struct table *t, int col, int cspan, double s, double b) -{ - int i, j; - int ecol = col + cspan; - int size = t->maxcol + 1; - double w = 1. / (b * b); - double ss; - - for (i = 0; i < size; i++) { - for (j = i; j < size; j++) { - if (i >= col && i < ecol && j >= col && j < ecol) - ss = (1. - s) * (1. - s); - else if ((i >= col && i < ecol) || (j >= col && j < ecol)) - ss = -(1. - s) * s; - else - ss = s * s; - m_add_val(t->matrix, i, j, w * ss); - } - } -} - -static void -correct_table_matrix3(struct table *t, int col, char *flags, double s, double b) -{ - int i, j; - double ss; - int size = t->maxcol + 1; - double w = 1. / (b * b); - int flg = (flags[col] == 0); - - for (i = 0; i < size; i++) { - if (!((flg && flags[i] == 0) || (!flg && flags[i] != 0))) - continue; - for (j = i; j < size; j++) { - if (!((flg && flags[j] == 0) || (!flg && flags[j] != 0))) - continue; - if (i == col && j == col) - ss = (1. - s) * (1. - s); - else if (i == col || j == col) - ss = -(1. - s) * s; - else - ss = s * s; - m_add_val(t->matrix, i, j, w * ss); - } - } -} - -static void -set_table_matrix0(struct table *t, int maxwidth) -{ - int size = t->maxcol + 1; - int i, j, k, bcol, ecol; - int swidth, width, a; - double w0, w1, w, s, b; -#ifdef __GNUC__ - double we[size]; - char expand[size]; -#else /* not __GNUC__ */ - double we[MAXCOL]; - char expand[MAXCOL]; -#endif /* not __GNUC__ */ - struct table_cell *cell = &t->cell; - - w0 = 0.; - for (i = 0; i < size; i++) { - we[i] = weight(t->tabwidth[i]); - w0 += we[i]; - } - if (w0 <= 0.) - w0 = 1.; - - if (cell->necell == 0) { - for (i = 0; i < size; i++) { - s = we[i] / w0; - b = sigma_td_nw((int) (s * maxwidth)); - correct_table_matrix2(t, i, 1, s, b); - } - return; - } - - bzero(expand, size); - - for (k = 0; k < cell->necell; k++) { - j = cell->eindex[k]; - bcol = cell->col[j]; - ecol = bcol + cell->colspan[j]; - swidth = 0; - for (i = bcol; i < ecol; i++) { - swidth += t->tabwidth[i]; - expand[i]++; - } - width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing; - w = weight(width); - w1 = 0.; - for (i = bcol; i < ecol; i++) - w1 += we[i]; - s = w / (w0 + w - w1); - a = (int) (s * maxwidth); - b = sigma_td_nw(a); - correct_table_matrix2(t, bcol, cell->colspan[j], s, b); - } - - w1 = 0.; - for (i = 0; i < size; i++) - if (expand[i] == 0) - w1 += we[i]; - for (i = 0; i < size; i++) { - if (expand[i] == 0) { - s = we[i] / max(w1, 1.); - b = sigma_td_nw((int) (s * maxwidth)); - } - else { - s = we[i] / max(w0 - w1, 1.); - b = sigma_td_nw(maxwidth); - } - correct_table_matrix3(t, i, expand, s, b); - } -} - -void -set_table_matrix(struct table *t, int width) -{ - int size = t->maxcol + 1; - int i, j; - double b, s; - int a; - struct table_cell *cell = &t->cell; - - if (size < 1) - return; - - t->matrix = m_get(size, size); - t->vector = v_get(size); - for (i = 0; i < size; i++) { - for (j = i; j < size; j++) - m_set_val(t->matrix, i, j, 0.); - v_set_val(t->vector, i, 0.); - } - - for (i = 0; i < size; i++) { - if (t->fixed_width[i] > 0) { - a = max(t->fixed_width[i], t->minimum_width[i]); - b = sigma_td(a); - correct_table_matrix(t, i, 1, a, b); - } - else if (t->fixed_width[i] < 0) { - s = -(double) t->fixed_width[i] / 100.; - b = sigma_td((int) (s * width)); - correct_table_matrix2(t, i, 1, s, b); - } - } - - for (j = 0; j <= cell->maxcell; j++) { - if (cell->fixed_width[j] > 0) { - a = max(cell->fixed_width[j], cell->minimum_width[j]); - b = sigma_td(a); - correct_table_matrix(t, cell->col[j], - cell->colspan[j], a, b); - } - else if (cell->fixed_width[j] < 0) { - s = -(double) cell->fixed_width[j] / 100.; - b = sigma_td((int) (s * width)); - correct_table_matrix2(t, cell->col[j], - cell->colspan[j], s, b); - } - } - - set_table_matrix0(t, width); - - if (t->total_width > 0) { - b = sigma_table(width); - } - else { - b = sigma_table_nw(width); - } - correct_table_matrix(t, 0, size, width, b); -} -#endif /* MATRIX */ |