* file.c (HTMLtagproc1): <s>..</s> is [S:...:S] (HTMLtagproc0): <del> will delete <table> * fm.h (RB_S): added * html.c (TagMAP): <s>,</s> move <internal>, </internal> * html.h (HTML_S): added (HTML_N_S): added (HTML_INTERNAL): renumed (HTML_N_INTERNAL): ditto (MAX_HTMLTAG): add 2 * rc.c (CMT_DISP_INS_DEL): update * table.c (feed_table_tag): add HTML_S, HTML_N_S * table.h (TBLM_S): added (TBLM_ANCHOR): renum * tagtable.tab: (strike, s): HTML_S (/strike, /s): HTML_N_S From: Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
		
			
				
	
	
		
			3552 lines
		
	
	
		
			82 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3552 lines
		
	
	
		
			82 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id: table.c,v 1.36 2002/12/06 16:50:41 ukai Exp $ */
 | 
						|
/* 
 | 
						|
 * HTML table
 | 
						|
 */
 | 
						|
#include <sys/types.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <math.h>
 | 
						|
#include "fm.h"
 | 
						|
#include "html.h"
 | 
						|
#include "parsetagx.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 */
 | 
						|
char alt_rule[] = {
 | 
						|
    '+', '|', '-', '+', '|', '|', '+', ' ', '-', '+', '-', ' ', '+', ' ', ' ',
 | 
						|
    ' '
 | 
						|
};
 | 
						|
#if defined(__EMX__)&&!defined(JP_CHARSET)
 | 
						|
extern int CodePage;
 | 
						|
 | 
						|
static char *_rule[] =
 | 
						|
#else
 | 
						|
static char *rule[] =
 | 
						|
#endif
 | 
						|
{
 | 
						|
    "<_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> </_RULE>",
 | 
						|
    "<_RULE TYPE=8>-</_RULE>",
 | 
						|
    "<_RULE TYPE=9>+</_RULE>",
 | 
						|
    "<_RULE TYPE=10>-</_RULE>",
 | 
						|
    "<_RULE TYPE=11> </_RULE>",
 | 
						|
    "<_RULE TYPE=12>+</_RULE>",
 | 
						|
    "<_RULE TYPE=13> </_RULE>",
 | 
						|
    "<_RULE TYPE=14> </_RULE>",
 | 
						|
    "<_RULE TYPE=15> </_RULE>"
 | 
						|
};
 | 
						|
#if defined(__EMX__)&&!defined(JP_CHARSET)
 | 
						|
static char **ruleB = _rule, **rule = _rule;
 | 
						|
static char *rule850[] = {
 | 
						|
    "\305", "\303", "\302", "\332", "\264", "\263", "\277", "07",
 | 
						|
    "\301", "\300", "\304", "0B", "\331", "0D", "0E", " "
 | 
						|
};
 | 
						|
static char *ruleB850[] = {
 | 
						|
    "\316", "\314", "\313", "\311" "\271", "\272", "\273", "07",
 | 
						|
    "\312", "\310", "\315", "0B", "\274", "0D", "0E", " "
 | 
						|
};
 | 
						|
#else				/* not __EMX__ or JP_CHARSET */
 | 
						|
static char **ruleB = rule;
 | 
						|
#endif				/* not __EMX__ or JP_CHARSET */
 | 
						|
 | 
						|
#define TN_VERTICALBAR "<_RULE TYPE=5>|</_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
 | 
						|
#define HTT_VALIGN 0x700
 | 
						|
#define HTT_TOP    0x100
 | 
						|
#define HTT_MIDDLE 0x200
 | 
						|
#define HTT_BOTTOM 0x400
 | 
						|
#define HTT_VTRSET 0x800
 | 
						|
#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
 | 
						|
bsearch_2short(short e1, short *ent1, short e2, short *ent2, int base,
 | 
						|
	       short *indexarray, int nent)
 | 
						|
{
 | 
						|
    int n = nent;
 | 
						|
    int k = 0;
 | 
						|
 | 
						|
    int e = e1 * base + e2;
 | 
						|
    while (n > 0) {
 | 
						|
	int nn = n / 2;
 | 
						|
	int idx = indexarray[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
 | 
						|
bsearch_double(double e, double *ent, short *indexarray, int nent)
 | 
						|
{
 | 
						|
    int n = nent;
 | 
						|
    int k = 0;
 | 
						|
 | 
						|
    while (n > 0) {
 | 
						|
	int nn = n / 2;
 | 
						|
	int idx = indexarray[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 int
 | 
						|
ceil_at_intervals(int x, int step)
 | 
						|
{
 | 
						|
    int mo = x % step;
 | 
						|
    if (mo > 0)
 | 
						|
	x += step - mo;
 | 
						|
    else if (mo < 0)
 | 
						|
	x -= mo;
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
floor_at_intervals(int x, int step)
 | 
						|
{
 | 
						|
    int mo = x % step;
 | 
						|
    if (mo > 0)
 | 
						|
	x -= mo;
 | 
						|
    else if (mo < 0)
 | 
						|
	x += step - mo;
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
#define round(x) ((int)floor((x)+0.5))
 | 
						|
 | 
						|
#ifndef MATRIX
 | 
						|
static void
 | 
						|
dv2sv(double *dv, short *iv, int size)
 | 
						|
{
 | 
						|
    int i, k, iw;
 | 
						|
    short *indexarray;
 | 
						|
    double *edv;
 | 
						|
    double w = 0., x;
 | 
						|
 | 
						|
    indexarray = NewAtom_N(short, 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 = bsearch_double(x, edv, indexarray, k);
 | 
						|
	if (k > i) {
 | 
						|
	    int ii;
 | 
						|
	    for (ii = i; ii < k; ii++)
 | 
						|
		indexarray[ii + 1] = indexarray[ii];
 | 
						|
	}
 | 
						|
	indexarray[i] = k;
 | 
						|
    }
 | 
						|
    iw = min((int)(w + 0.5), size);
 | 
						|
    if (iw == 0)
 | 
						|
	return;
 | 
						|
    x = edv[(int)indexarray[iw - 1]];
 | 
						|
    for (i = 0; i < size; i++) {
 | 
						|
	k = indexarray[i];
 | 
						|
	if (i >= iw && abs(edv[k] - x) > 1e-6)
 | 
						|
	    break;
 | 
						|
	iv[k]--;
 | 
						|
    }
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
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(GeneralList **, 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->ntable = 0;
 | 
						|
    t->tables_size = 0;
 | 
						|
    t->tables = NULL;
 | 
						|
#ifdef MATRIX
 | 
						|
    t->matrix = NULL;
 | 
						|
    t->vector = NULL;
 | 
						|
#endif				/* MATRIX */
 | 
						|
#if 0
 | 
						|
    t->tabcontentssize = 0;
 | 
						|
    t->indent = 0;
 | 
						|
    t->linfo.prev_ctype = PC_ASCII;
 | 
						|
    t->linfo.prev_spaces = -1;
 | 
						|
    t->linfo.prevchar = ' ';
 | 
						|
#endif
 | 
						|
    t->trattr = 0;
 | 
						|
 | 
						|
    t->caption = Strnew();
 | 
						|
    t->suspended_data = NULL;
 | 
						|
#ifdef ID_EXT
 | 
						|
    t->id = NULL;
 | 
						|
#endif
 | 
						|
    return t;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
check_row(struct table *t, int row)
 | 
						|
{
 | 
						|
    int i, r;
 | 
						|
    GeneralList ***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(GeneralList **, r);
 | 
						|
	tabattr = New_N(table_attr *, r);
 | 
						|
	tabheight = NewAtom_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(GeneralList *, 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] = newGeneralList();
 | 
						|
 | 
						|
    pushText(t->tabdata[row][col], data);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
suspend_or_pushdata(struct table *tbl, char *line)
 | 
						|
{
 | 
						|
    if (tbl->flag & TBL_IN_COL)
 | 
						|
	pushdata(tbl, tbl->row, tbl->col, line);
 | 
						|
    else {
 | 
						|
	if (!tbl->suspended_data)
 | 
						|
	    tbl->suspended_data = newTextList();
 | 
						|
	pushText(tbl->suspended_data, line);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int visible_length_offset = 0;
 | 
						|
int
 | 
						|
visible_length(char *str)
 | 
						|
{
 | 
						|
    int len = 0, max_len = 0;
 | 
						|
    int status = R_ST_NORMAL;
 | 
						|
    int prev_status = status;
 | 
						|
    Str tagbuf = Strnew();
 | 
						|
    char *t, *r2;
 | 
						|
    int amp_len = 0;
 | 
						|
 | 
						|
    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);
 | 
						|
		len--;
 | 
						|
		amp_len = 0;
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		Strcat_char(tagbuf, *str);
 | 
						|
		amp_len++;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else if (status == R_ST_NORMAL && prev_status == R_ST_AMP) {
 | 
						|
	    Strcat_char(tagbuf, *str);
 | 
						|
	    r2 = tagbuf->ptr;
 | 
						|
	    t = getescapecmd(&r2);
 | 
						|
	    if (!*r2 && (*t == '\r' || *t == '\n')) {
 | 
						|
		if (len > max_len)
 | 
						|
		    max_len = len;
 | 
						|
		len = 0;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
		len += strlen(t) + strlen(r2);
 | 
						|
	}
 | 
						|
	else if (status == R_ST_NORMAL && ST_IS_REAL_TAG(prev_status)) {
 | 
						|
	    ;
 | 
						|
	}
 | 
						|
	else if (*str == '\t') {
 | 
						|
	    len--;
 | 
						|
	    do {
 | 
						|
		len++;
 | 
						|
	    } while ((visible_length_offset + len) % Tabstop != 0);
 | 
						|
	}
 | 
						|
	else if (*str == '\r' || *str == '\n') {
 | 
						|
	    len--;
 | 
						|
	    if (len > max_len)
 | 
						|
		max_len = len;
 | 
						|
	    len = 0;
 | 
						|
	}
 | 
						|
	str++;
 | 
						|
    }
 | 
						|
    if (status == R_ST_AMP) {
 | 
						|
	r2 = tagbuf->ptr;
 | 
						|
	t = getescapecmd(&r2);
 | 
						|
	if (*t != '\r' && *t != '\n')
 | 
						|
	    len += strlen(t) + strlen(r2);
 | 
						|
    }
 | 
						|
    return len > max_len ? len : max_len;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
visible_length_plain(char *str)
 | 
						|
{
 | 
						|
    int len = 0, max_len = 0;
 | 
						|
 | 
						|
    while (*str) {
 | 
						|
	if (*str == '\t') {
 | 
						|
	    do {
 | 
						|
		len++;
 | 
						|
	    } while ((visible_length_offset + len) % Tabstop != 0);
 | 
						|
	}
 | 
						|
	else if (*str == '\r' || *str == '\n') {
 | 
						|
	    if (len > max_len)
 | 
						|
		max_len = len;
 | 
						|
	    len = 0;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    len++;
 | 
						|
	str++;
 | 
						|
    }
 | 
						|
    return len > max_len ? len : max_len;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
maximum_visible_length(char *str)
 | 
						|
{
 | 
						|
    int maxlen, len;
 | 
						|
 | 
						|
    visible_length_offset = 0;
 | 
						|
    maxlen = visible_length(str);
 | 
						|
 | 
						|
    if (!strchr(str, '\t'))
 | 
						|
	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;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
maximum_visible_length_plain(char *str)
 | 
						|
{
 | 
						|
    int maxlen, len;
 | 
						|
 | 
						|
    visible_length_offset = 0;
 | 
						|
    maxlen = visible_length_plain(str);
 | 
						|
 | 
						|
    if (!strchr(str, '\t'))
 | 
						|
	return maxlen;
 | 
						|
 | 
						|
    for (visible_length_offset = 1; visible_length_offset < Tabstop;
 | 
						|
	 visible_length_offset++) {
 | 
						|
	len = visible_length_plain(str);
 | 
						|
	if (maxlen < len) {
 | 
						|
	    maxlen = len;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return maxlen;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
align(TextLine *lbuf, int width, int mode)
 | 
						|
{
 | 
						|
    int i, l, l1, l2;
 | 
						|
    Str buf, line = lbuf->line;
 | 
						|
 | 
						|
    if (line->length == 0) {
 | 
						|
	for (i = 0; i < width; i++)
 | 
						|
	    Strcat_char(line, ' ');
 | 
						|
	lbuf->pos = width;
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    buf = Strnew();
 | 
						|
    l = width - lbuf->pos;
 | 
						|
    switch (mode) {
 | 
						|
    case ALIGN_CENTER:
 | 
						|
	l1 = l / 2;
 | 
						|
	l2 = l - l1;
 | 
						|
	for (i = 0; i < l1; i++)
 | 
						|
	    Strcat_char(buf, ' ');
 | 
						|
	Strcat(buf, line);
 | 
						|
	for (i = 0; i < l2; i++)
 | 
						|
	    Strcat_char(buf, ' ');
 | 
						|
	break;
 | 
						|
    case ALIGN_LEFT:
 | 
						|
	Strcat(buf, line);
 | 
						|
	for (i = 0; i < l; i++)
 | 
						|
	    Strcat_char(buf, ' ');
 | 
						|
	break;
 | 
						|
    case ALIGN_RIGHT:
 | 
						|
	for (i = 0; i < l; i++)
 | 
						|
	    Strcat_char(buf, ' ');
 | 
						|
	Strcat(buf, line);
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    lbuf->line = buf;
 | 
						|
    if (lbuf->pos < width)
 | 
						|
	lbuf->pos = width;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
print_item(struct table *t, int row, int col, int width, Str buf)
 | 
						|
{
 | 
						|
    int alignment;
 | 
						|
    TextLine *lbuf;
 | 
						|
 | 
						|
    if (t->tabdata[row])
 | 
						|
	lbuf = popTextLine(t->tabdata[row][col]);
 | 
						|
    else
 | 
						|
	lbuf = NULL;
 | 
						|
 | 
						|
    if (lbuf != 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;
 | 
						|
	align(lbuf, width, alignment);
 | 
						|
	Strcat(buf, lbuf->line);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	lbuf = newTextLine(NULL, 0);
 | 
						|
	align(lbuf, width, ALIGN_CENTER);
 | 
						|
	Strcat(buf, lbuf->line);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#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]);
 | 
						|
}
 | 
						|
 | 
						|
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, int maxlimit)
 | 
						|
{
 | 
						|
    TextList *orgdata;
 | 
						|
    TextListItem *l;
 | 
						|
    struct readbuffer obuf;
 | 
						|
    struct html_feed_environ h_env;
 | 
						|
    struct environment envs[MAX_ENV_LEVEL];
 | 
						|
    int colspan, icell;
 | 
						|
 | 
						|
    if (tbl->tabdata[row] == NULL || tbl->tabdata[row][col] == NULL)
 | 
						|
	return;
 | 
						|
    orgdata = (TextList *)tbl->tabdata[row][col];
 | 
						|
    tbl->tabdata[row][col] = newGeneralList();
 | 
						|
 | 
						|
    init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL,
 | 
						|
	      (TextLineList *)tbl->tabdata[row][col],
 | 
						|
	      get_spec_cell_width(tbl, row, col), 0);
 | 
						|
    obuf.flag |= RB_INTABLE;
 | 
						|
    if (h_env.limit > maxlimit)
 | 
						|
	h_env.limit = maxlimit;
 | 
						|
    if (tbl->border_mode != BORDER_NONE && tbl->vcellpadding > 0)
 | 
						|
	do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
 | 
						|
    for (l = orgdata->first; l != NULL; l = l->next) {
 | 
						|
	if (TAG_IS(l->ptr, "<table_alt", 10)) {
 | 
						|
	    int id = -1;
 | 
						|
	    char *p = l->ptr;
 | 
						|
	    struct parsed_tag *tag;
 | 
						|
	    if ((tag = parse_tag(&p, TRUE)) != NULL)
 | 
						|
		parsedtag_get_value(tag, ATTR_TID, &id);
 | 
						|
	    if (id >= 0 && id < tbl->ntable) {
 | 
						|
		int alignment;
 | 
						|
		TextLineListItem *ti;
 | 
						|
		struct table *t = tbl->tables[id].ptr;
 | 
						|
		int limit = tbl->tables[id].indent + t->total_width;
 | 
						|
		tbl->tables[id].ptr = NULL;
 | 
						|
		save_fonteffect(&h_env, h_env.obuf);
 | 
						|
		flushline(&h_env, &obuf, 0, 2, h_env.limit);
 | 
						|
		if (t->vspace > 0 && !(obuf.flag & RB_IGNORE_P))
 | 
						|
		    do_blankline(&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) {
 | 
						|
		    for (ti = tbl->tables[id].buf->first;
 | 
						|
			 ti != NULL; ti = ti->next)
 | 
						|
			align(ti->ptr, h_env.limit, alignment);
 | 
						|
		}
 | 
						|
		appendTextLineList(h_env.buf, tbl->tables[id].buf);
 | 
						|
		if (h_env.maxlimit < limit)
 | 
						|
		    h_env.maxlimit = limit;
 | 
						|
		restore_fonteffect(&h_env, h_env.obuf);
 | 
						|
		obuf.flag &= ~RB_IGNORE_P;
 | 
						|
		h_env.blank_lines = 0;
 | 
						|
		if (t->vspace > 0) {
 | 
						|
		    do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
 | 
						|
		    obuf.flag |= RB_IGNORE_P;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    HTMLlineproc1(l->ptr, &h_env);
 | 
						|
    }
 | 
						|
    if (obuf.status != R_ST_NORMAL) {
 | 
						|
	obuf.status = R_ST_EOL;
 | 
						|
	HTMLlineproc1("\n", &h_env);
 | 
						|
    }
 | 
						|
    completeHTMLstream(&h_env, &obuf);
 | 
						|
    flushline(&h_env, &obuf, 0, 2, h_env.limit);
 | 
						|
    if (tbl->border_mode == BORDER_NONE) {
 | 
						|
	int rowspan = table_rowspan(tbl, row, col);
 | 
						|
	if (row + rowspan <= tbl->maxrow) {
 | 
						|
	    if (tbl->vcellpadding > 0 && !(obuf.flag & RB_IGNORE_P))
 | 
						|
		do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (tbl->vspace > 0)
 | 
						|
		purgeline(&h_env);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	if (tbl->vcellpadding > 0) {
 | 
						|
	    if (!(obuf.flag & RB_IGNORE_P))
 | 
						|
		do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    purgeline(&h_env);
 | 
						|
    }
 | 
						|
    if ((colspan = table_colspan(tbl, row, col)) > 1) {
 | 
						|
	struct table_cell *cell = &tbl->cell;
 | 
						|
	int k;
 | 
						|
	k = bsearch_2short(colspan, cell->colspan, col, cell->col, MAXCOL,
 | 
						|
			   cell->index, cell->maxcell + 1);
 | 
						|
	icell = cell->index[k];
 | 
						|
	if (cell->minimum_width[icell] < h_env.maxlimit)
 | 
						|
	    cell->minimum_width[icell] = h_env.maxlimit;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	if (tbl->minimum_width[col] < h_env.maxlimit)
 | 
						|
	    tbl->minimum_width[col] = h_env.maxlimit;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
table_rule_width(struct table *t)
 | 
						|
{
 | 
						|
    if (t->border_mode == BORDER_NONE)
 | 
						|
	return 1;
 | 
						|
    return RULE_WIDTH;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
check_cell_width(short *tabwidth, short *cellwidth,
 | 
						|
		 short *col, short *colspan, short maxcell,
 | 
						|
		 short *indexarray, int space, int dir)
 | 
						|
{
 | 
						|
    int i, j, k, bcol, ecol;
 | 
						|
    int swidth, width;
 | 
						|
 | 
						|
    for (k = 0; k <= maxcell; k++) {
 | 
						|
	j = indexarray[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 void
 | 
						|
set_integered_width(struct table *t, double *dwidth, short *iwidth)
 | 
						|
{
 | 
						|
    int i, j, k, n, bcol, ecol, step;
 | 
						|
    short *indexarray;
 | 
						|
    char *fixed;
 | 
						|
    double *mod;
 | 
						|
    double sum = 0., x = 0.;
 | 
						|
    struct table_cell *cell = &t->cell;
 | 
						|
    int rulewidth = table_rule_width(t);
 | 
						|
 | 
						|
    indexarray = NewAtom_N(short, t->maxcol + 1);
 | 
						|
    mod = NewAtom_N(double, t->maxcol + 1);
 | 
						|
    for (i = 0; i <= t->maxcol; i++) {
 | 
						|
	iwidth[i] = ceil_at_intervals(ceil(dwidth[i]), rulewidth);
 | 
						|
	mod[i] = (double)iwidth[i] - dwidth[i];
 | 
						|
    }
 | 
						|
 | 
						|
    sum = 0.;
 | 
						|
    for (k = 0; k <= t->maxcol; k++) {
 | 
						|
	x = mod[k];
 | 
						|
	sum += x;
 | 
						|
	i = bsearch_double(x, mod, indexarray, k);
 | 
						|
	if (k > i) {
 | 
						|
	    int ii;
 | 
						|
	    for (ii = i; ii < k; ii++)
 | 
						|
		indexarray[ii + 1] = indexarray[ii];
 | 
						|
	}
 | 
						|
	indexarray[i] = k;
 | 
						|
    }
 | 
						|
 | 
						|
    fixed = NewAtom_N(char, t->maxcol + 1);
 | 
						|
    bzero(fixed, t->maxcol + 1);
 | 
						|
    for (step = 0; step < 2; step++) {
 | 
						|
	for (i = 0; i <= t->maxcol; i += n) {
 | 
						|
	    int nn;
 | 
						|
	    char *idx;
 | 
						|
	    double nsum;
 | 
						|
	    if (sum < 0.5)
 | 
						|
		return;
 | 
						|
	    for (n = 0; i + n <= t->maxcol; n++) {
 | 
						|
		int ii = indexarray[i + n];
 | 
						|
		if (n == 0)
 | 
						|
		    x = mod[ii];
 | 
						|
		else if (fabs(mod[ii] - x) > 1e-6)
 | 
						|
		    break;
 | 
						|
	    }
 | 
						|
	    for (k = 0; k < n; k++) {
 | 
						|
		int ii = indexarray[i + k];
 | 
						|
		if (fixed[ii] < 2 &&
 | 
						|
		    iwidth[ii] - rulewidth < t->minimum_width[ii])
 | 
						|
		    fixed[ii] = 2;
 | 
						|
		if (fixed[ii] < 1 &&
 | 
						|
		    iwidth[ii] - rulewidth < t->tabwidth[ii] &&
 | 
						|
		    (double)rulewidth - mod[ii] > 0.5)
 | 
						|
		    fixed[ii] = 1;
 | 
						|
	    }
 | 
						|
	    idx = NewAtom_N(char, n);
 | 
						|
	    for (k = 0; k < cell->maxcell; k++) {
 | 
						|
		int kk, w, width, m;
 | 
						|
		j = cell->index[k];
 | 
						|
		bcol = cell->col[j];
 | 
						|
		ecol = bcol + cell->colspan[j];
 | 
						|
		m = 0;
 | 
						|
		for (kk = 0; kk < n; kk++) {
 | 
						|
		    int ii = indexarray[i + kk];
 | 
						|
		    if (ii >= bcol && ii < ecol) {
 | 
						|
			idx[m] = ii;
 | 
						|
			m++;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		if (m == 0)
 | 
						|
		    continue;
 | 
						|
		width = (cell->colspan[j] - 1) * t->cellspacing;
 | 
						|
		for (kk = bcol; kk < ecol; kk++)
 | 
						|
		    width += iwidth[kk];
 | 
						|
		w = 0;
 | 
						|
		for (kk = 0; kk < m; kk++) {
 | 
						|
		    if (fixed[(int)idx[kk]] < 2)
 | 
						|
			w += rulewidth;
 | 
						|
		}
 | 
						|
		if (width - w < cell->minimum_width[j]) {
 | 
						|
		    for (kk = 0; kk < m; kk++) {
 | 
						|
			if (fixed[(int)idx[kk]] < 2)
 | 
						|
			    fixed[(int)idx[kk]] = 2;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		w = 0;
 | 
						|
		for (kk = 0; kk < m; kk++) {
 | 
						|
		    if (fixed[(int)idx[kk]] < 1 &&
 | 
						|
			(double)rulewidth - mod[(int)idx[kk]] > 0.5)
 | 
						|
			w += rulewidth;
 | 
						|
		}
 | 
						|
		if (width - w < cell->width[j]) {
 | 
						|
		    for (kk = 0; kk < m; kk++) {
 | 
						|
			if (fixed[(int)idx[kk]] < 1 &&
 | 
						|
			    (double)rulewidth - mod[(int)idx[kk]] > 0.5)
 | 
						|
			    fixed[(int)idx[kk]] = 1;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    nn = 0;
 | 
						|
	    for (k = 0; k < n; k++) {
 | 
						|
		int ii = indexarray[i + k];
 | 
						|
		if (fixed[ii] <= step)
 | 
						|
		    nn++;
 | 
						|
	    }
 | 
						|
	    nsum = sum - (double)(nn * rulewidth);
 | 
						|
	    if (nsum < 0. && fabs(sum) <= fabs(nsum))
 | 
						|
		return;
 | 
						|
	    for (k = 0; k < n; k++) {
 | 
						|
		int ii = indexarray[i + k];
 | 
						|
		if (fixed[ii] <= step) {
 | 
						|
		    iwidth[ii] -= rulewidth;
 | 
						|
		    fixed[ii] = 3;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    sum = nsum;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static double
 | 
						|
correlation_coefficient(double sxx, double syy, double sxy)
 | 
						|
{
 | 
						|
    double coe, tmp;
 | 
						|
    tmp = sxx * syy;
 | 
						|
    if (tmp < Tiny)
 | 
						|
	tmp = Tiny;
 | 
						|
    coe = sxy / sqrt(tmp);
 | 
						|
    if (coe > 1.)
 | 
						|
	return 1.;
 | 
						|
    if (coe < -1.)
 | 
						|
	return -1.;
 | 
						|
    return coe;
 | 
						|
}
 | 
						|
 | 
						|
static double
 | 
						|
correlation_coefficient2(double sxx, double syy, double sxy)
 | 
						|
{
 | 
						|
    double coe, tmp;
 | 
						|
    tmp = (syy + sxx - 2 * sxy) * sxx;
 | 
						|
    if (tmp < Tiny)
 | 
						|
	tmp = Tiny;
 | 
						|
    coe = (sxx - sxy) / sqrt(tmp);
 | 
						|
    if (coe > 1.)
 | 
						|
	return 1.;
 | 
						|
    if (coe < -1.)
 | 
						|
	return -1.;
 | 
						|
    return coe;
 | 
						|
}
 | 
						|
 | 
						|
static double
 | 
						|
recalc_width(double old, double swidth, int cwidth,
 | 
						|
	     double sxx, double syy, double sxy, int is_inclusive)
 | 
						|
{
 | 
						|
    double delta = swidth - (double)cwidth;
 | 
						|
    double rat = sxy / sxx,
 | 
						|
	coe = correlation_coefficient(sxx, syy, sxy), w, ww;
 | 
						|
    if (old < 0.)
 | 
						|
	old = 0.;
 | 
						|
    if (fabs(coe) < 1e-5)
 | 
						|
	return old;
 | 
						|
    w = rat * old;
 | 
						|
    ww = delta;
 | 
						|
    if (w > 0.) {
 | 
						|
	double wmin = 5e-3 * sqrt(syy * (1. - coe * coe));
 | 
						|
	if (swidth < 0.2 && cwidth > 0 && is_inclusive) {
 | 
						|
	    double coe1 = correlation_coefficient2(sxx, syy, sxy);
 | 
						|
	    if (coe > 0.9 || coe1 > 0.9)
 | 
						|
		return 0.;
 | 
						|
	}
 | 
						|
	if (wmin > 0.05)
 | 
						|
	    wmin = 0.05;
 | 
						|
	if (ww < 0.)
 | 
						|
	    ww = 0.;
 | 
						|
	ww += wmin;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	double wmin = 5e-3 * sqrt(syy) * fabs(coe);
 | 
						|
	if (rat > -0.001)
 | 
						|
	    return old;
 | 
						|
	if (wmin > 0.01)
 | 
						|
	    wmin = 0.01;
 | 
						|
	if (ww > 0.)
 | 
						|
	    ww = 0.;
 | 
						|
	ww -= wmin;
 | 
						|
    }
 | 
						|
    if (w > ww)
 | 
						|
	return ww / rat;
 | 
						|
    return old;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
check_compressible_cell(struct table *t, MAT * minv,
 | 
						|
			double *newwidth, double *swidth, short *cwidth,
 | 
						|
			double totalwidth, double *Sxx,
 | 
						|
			int icol, int icell, double sxx, int corr)
 | 
						|
{
 | 
						|
    struct table_cell *cell = &t->cell;
 | 
						|
    int i, j, k, m, bcol, ecol, span;
 | 
						|
    double delta, owidth;
 | 
						|
    double dmax, dmin, sxy;
 | 
						|
    int rulewidth = table_rule_width(t);
 | 
						|
 | 
						|
    if (sxx < 10.)
 | 
						|
	return corr;
 | 
						|
 | 
						|
    if (icol >= 0) {
 | 
						|
	owidth = newwidth[icol];
 | 
						|
	delta = newwidth[icol] - (double)t->tabwidth[icol];
 | 
						|
	bcol = icol;
 | 
						|
	ecol = bcol + 1;
 | 
						|
    }
 | 
						|
    else if (icell >= 0) {
 | 
						|
	owidth = swidth[icell];
 | 
						|
	delta = swidth[icell] - (double)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 = -1.;
 | 
						|
    for (k = 0; k <= cell->maxcell; k++) {
 | 
						|
	int bcol1, ecol1;
 | 
						|
	int is_inclusive = 0;
 | 
						|
	if (dmin <= 0.)
 | 
						|
	    goto _end;
 | 
						|
	j = cell->index[k];
 | 
						|
	if (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 (bcol1 >= bcol && ecol1 <= ecol) {
 | 
						|
	    is_inclusive = 1;
 | 
						|
	}
 | 
						|
	if (sxy > 0.)
 | 
						|
	    dmin = recalc_width(dmin, swidth[j], cwidth[j],
 | 
						|
				sxx, Sxx[j], sxy, is_inclusive);
 | 
						|
	else
 | 
						|
	    dmax = recalc_width(dmax, swidth[j], cwidth[j],
 | 
						|
				sxx, Sxx[j], sxy, is_inclusive);
 | 
						|
    }
 | 
						|
    for (m = 0; m <= t->maxcol; m++) {
 | 
						|
	int is_inclusive = 0;
 | 
						|
	if (dmin <= 0.)
 | 
						|
	    goto _end;
 | 
						|
	if (m == icol)
 | 
						|
	    continue;
 | 
						|
	sxy = 0.;
 | 
						|
	for (i = bcol; i < ecol; i++)
 | 
						|
	    sxy += m_entry(minv, i, m);
 | 
						|
	if (m >= bcol && m < ecol) {
 | 
						|
	    is_inclusive = 1;
 | 
						|
	}
 | 
						|
	if (sxy > 0.)
 | 
						|
	    dmin = recalc_width(dmin, newwidth[m], t->tabwidth[m],
 | 
						|
				sxx, m_entry(minv, m, m), sxy, is_inclusive);
 | 
						|
	else
 | 
						|
	    dmax = recalc_width(dmax, newwidth[m], t->tabwidth[m],
 | 
						|
				sxx, m_entry(minv, m, m), sxy, is_inclusive);
 | 
						|
    }
 | 
						|
  _end:
 | 
						|
    if (dmax > 0. && dmin > dmax)
 | 
						|
	dmin = dmax;
 | 
						|
    span = ecol - bcol;
 | 
						|
    if ((span == t->maxcol + 1 && dmin >= 0.) ||
 | 
						|
	(span != t->maxcol + 1 && dmin > rulewidth * 0.5)) {
 | 
						|
	int nwidth = ceil_at_intervals(round(owidth - dmin), rulewidth);
 | 
						|
	correct_table_matrix(t, bcol, ecol - bcol, nwidth, 1.);
 | 
						|
	corr++;
 | 
						|
    }
 | 
						|
    return corr;
 | 
						|
}
 | 
						|
 | 
						|
#define MAX_ITERATION 10
 | 
						|
int
 | 
						|
check_table_width(struct table *t, double *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], corwidth[t->maxcol + 1];
 | 
						|
    short cwidth[cell->maxcell + 1];
 | 
						|
    double swidth[cell->maxcell + 1];
 | 
						|
#else				/* __GNUC__ */
 | 
						|
    short orgwidth[MAXCOL], corwidth[MAXCOL];
 | 
						|
    short cwidth[MAXCELL];
 | 
						|
    double swidth[MAXCELL];
 | 
						|
#endif				/* __GNUC__ */
 | 
						|
    double twidth, 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, Sxx, -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, Sxx,
 | 
						|
				       -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, Sxx,
 | 
						|
				       i, -1, m_entry(minv, i, i), corr);
 | 
						|
	if (itr < MAX_ITERATION && corr > 0)
 | 
						|
	    return corr;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    for (i = 0; i <= t->maxcol; i++)
 | 
						|
	corwidth[i] = orgwidth[i] = round(newwidth[i]);
 | 
						|
 | 
						|
    check_minimum_width(t, corwidth);
 | 
						|
 | 
						|
    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] &&
 | 
						|
	    corwidth[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 += corwidth[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->indexarray[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;
 | 
						|
	short *rowspan;
 | 
						|
	short *indexarray;
 | 
						|
	short maxcell;
 | 
						|
	short size;
 | 
						|
	short *height;
 | 
						|
    } cell;
 | 
						|
    int space = 0;
 | 
						|
 | 
						|
    cell.size = 0;
 | 
						|
    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 = bsearch_2short(rowspan, cell.rowspan,
 | 
						|
				   j, cell.row, t->maxrow + 1, cell.indexarray,
 | 
						|
				   c);
 | 
						|
		if (k <= cell.maxcell) {
 | 
						|
		    int idx = cell.indexarray[k];
 | 
						|
		    if (cell.row[idx] == j && cell.rowspan[idx] == rowspan)
 | 
						|
			c = idx;
 | 
						|
		}
 | 
						|
		if (c >= MAXROWCELL)
 | 
						|
		    continue;
 | 
						|
		if (c >= cell.size) {
 | 
						|
		    if (cell.size == 0) {
 | 
						|
			cell.size = max(MAXCELL, c + 1);
 | 
						|
			cell.row = NewAtom_N(short, cell.size);
 | 
						|
			cell.rowspan = NewAtom_N(short, cell.size);
 | 
						|
			cell.indexarray = NewAtom_N(short, cell.size);
 | 
						|
			cell.height = NewAtom_N(short, cell.size);
 | 
						|
		    }
 | 
						|
		    else {
 | 
						|
			cell.size = max(cell.size + MAXCELL, c + 1);
 | 
						|
			cell.row = New_Reuse(short, cell.row, cell.size);
 | 
						|
			cell.rowspan = New_Reuse(short, cell.rowspan,
 | 
						|
						 cell.size);
 | 
						|
			cell.indexarray = New_Reuse(short, cell.indexarray,
 | 
						|
						    cell.size);
 | 
						|
			cell.height = New_Reuse(short, cell.height, cell.size);
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		if (c > cell.maxcell) {
 | 
						|
		    cell.maxcell++;
 | 
						|
		    cell.row[cell.maxcell] = j;
 | 
						|
		    cell.rowspan[cell.maxcell] = rowspan;
 | 
						|
		    cell.height[cell.maxcell] = 0;
 | 
						|
		    if (cell.maxcell > k) {
 | 
						|
			int ii;
 | 
						|
			for (ii = k; ii < cell.maxcell; ii++)
 | 
						|
			    cell.indexarray[ii + 1] = cell.indexarray[ii];
 | 
						|
		    }
 | 
						|
		    cell.indexarray[k] = cell.maxcell;
 | 
						|
		}
 | 
						|
 | 
						|
		if (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.indexarray, space, 1);
 | 
						|
}
 | 
						|
 | 
						|
#define CHECK_MINIMUM	1
 | 
						|
#define CHECK_FIXED	2
 | 
						|
 | 
						|
int
 | 
						|
get_table_width(struct table *t, short *orgwidth, short *cellwidth, int flag)
 | 
						|
{
 | 
						|
#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;
 | 
						|
    int rulewidth = table_rule_width(t);
 | 
						|
 | 
						|
    for (i = 0; i <= t->maxcol; i++)
 | 
						|
	newwidth[i] = max(orgwidth[i], 0);
 | 
						|
 | 
						|
    if (flag & CHECK_FIXED) {
 | 
						|
#ifdef __GNUC__
 | 
						|
	short ccellwidth[cell->maxcell + 1];
 | 
						|
#else				/* not __GNUC__ */
 | 
						|
	short ccellwidth[MAXCELL];
 | 
						|
#endif				/* not __GNUC__ */
 | 
						|
	for (i = 0; i <= t->maxcol; i++) {
 | 
						|
	    if (newwidth[i] < t->fixed_width[i])
 | 
						|
		newwidth[i] = t->fixed_width[i];
 | 
						|
	}
 | 
						|
	for (i = 0; i <= cell->maxcell; i++) {
 | 
						|
	    ccellwidth[i] = cellwidth[i];
 | 
						|
	    if (ccellwidth[i] < cell->fixed_width[i])
 | 
						|
		ccellwidth[i] = cell->fixed_width[i];
 | 
						|
	}
 | 
						|
	check_cell_width(newwidth, ccellwidth, cell->col, cell->colspan,
 | 
						|
			 cell->maxcell, cell->index, t->cellspacing, 0);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	check_cell_width(newwidth, cellwidth, cell->col, cell->colspan,
 | 
						|
			 cell->maxcell, cell->index, t->cellspacing, 0);
 | 
						|
    }
 | 
						|
    if (flag & CHECK_MINIMUM)
 | 
						|
	check_minimum_width(t, newwidth);
 | 
						|
 | 
						|
    swidth = 0;
 | 
						|
    for (i = 0; i <= t->maxcol; i++) {
 | 
						|
	swidth += ceil_at_intervals(newwidth[i], rulewidth);
 | 
						|
    }
 | 
						|
    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,CHECK_FIXED))
 | 
						|
#define fixed_table_width(t)\
 | 
						|
  (get_table_width(t,t->fixed_width,t->cell.fixed_width,CHECK_MINIMUM))
 | 
						|
 | 
						|
void
 | 
						|
renderCoTable(struct table *tbl, int maxlimit)
 | 
						|
{
 | 
						|
    struct readbuffer obuf;
 | 
						|
    struct html_feed_environ h_env;
 | 
						|
    struct environment envs[MAX_ENV_LEVEL];
 | 
						|
    struct table *t;
 | 
						|
    int i, col, row;
 | 
						|
    int indent, maxwidth;
 | 
						|
 | 
						|
    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,
 | 
						|
		  get_spec_cell_width(tbl, row, col), indent);
 | 
						|
	check_row(tbl, row);
 | 
						|
	if (h_env.limit > maxlimit)
 | 
						|
	    h_env.limit = maxlimit;
 | 
						|
	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 * h_env.limit / 100;
 | 
						|
	renderTable(t, maxwidth, &h_env);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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];
 | 
						|
    int limit;
 | 
						|
 | 
						|
    if (t->caption->length <= 0)
 | 
						|
	return;
 | 
						|
 | 
						|
    if (t->total_width > 0)
 | 
						|
	limit = t->total_width;
 | 
						|
    else
 | 
						|
	limit = h_env->limit;
 | 
						|
    init_henv(&henv, &obuf, envs, MAX_ENV_LEVEL, newTextLineList(),
 | 
						|
	      limit, h_env->envs[h_env->envc].indent);
 | 
						|
    HTMLlineproc1("<center>", &henv);
 | 
						|
    HTMLlineproc0(t->caption->ptr, &henv, FALSE);
 | 
						|
    HTMLlineproc1("</center>", &henv);
 | 
						|
 | 
						|
    if (t->total_width < henv.maxlimit)
 | 
						|
	t->total_width = henv.maxlimit;
 | 
						|
    limit = h_env->limit;
 | 
						|
    h_env->limit = t->total_width;
 | 
						|
    HTMLlineproc1("<center>", h_env);
 | 
						|
    HTMLlineproc0(t->caption->ptr, h_env, FALSE);
 | 
						|
    HTMLlineproc1("</center>", h_env);
 | 
						|
    h_env->limit = limit;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
renderTable(struct table *t, int max_width, struct html_feed_environ *h_env)
 | 
						|
{
 | 
						|
    int i, j, w, r, h;
 | 
						|
    Str renderbuf;
 | 
						|
    short new_tabwidth[MAXCOL];
 | 
						|
#ifdef MATRIX
 | 
						|
    int itr;
 | 
						|
    VEC *newwidth;
 | 
						|
    MAT *mat, *minv;
 | 
						|
    PERM *pivot;
 | 
						|
#endif				/* MATRIX */
 | 
						|
    int width;
 | 
						|
    int rulewidth;
 | 
						|
    Str vrulea = NULL, vruleb = NULL, vrulec = NULL;
 | 
						|
#ifdef ID_EXT
 | 
						|
    Str idtag;
 | 
						|
#endif				/* ID_EXT */
 | 
						|
 | 
						|
    t->total_height = 0;
 | 
						|
    if (t->maxcol < 0) {
 | 
						|
	make_caption(t, h_env);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (t->sloppy_width > max_width)
 | 
						|
	max_width = t->sloppy_width;
 | 
						|
 | 
						|
    rulewidth = table_rule_width(t);
 | 
						|
 | 
						|
    max_width -= table_border_width(t);
 | 
						|
 | 
						|
    if (rulewidth > 1)
 | 
						|
	max_width = floor_at_intervals(max_width, rulewidth);
 | 
						|
 | 
						|
    if (max_width < rulewidth)
 | 
						|
	max_width = rulewidth;
 | 
						|
 | 
						|
    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);
 | 
						|
	    LUinverse(mat, pivot, minv);
 | 
						|
#ifdef TABLE_DEBUG
 | 
						|
	    set_integered_width(t, newwidth->ve, new_tabwidth);
 | 
						|
	    fprintf(stderr, "itr=%d\n", itr);
 | 
						|
	    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, "\nfixed : ");
 | 
						|
	    for (i = 0; i <= t->maxcol; i++)
 | 
						|
		fprintf(stderr, "%2d ", t->fixed_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, newwidth->ve, minv, itr));
 | 
						|
	set_integered_width(t, newwidth->ve, new_tabwidth);
 | 
						|
	check_minimum_width(t, new_tabwidth);
 | 
						|
	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 */
 | 
						|
 | 
						|
    check_minimum_width(t, t->tabwidth);
 | 
						|
    for (i = 0; i <= t->maxcol; i++)
 | 
						|
	t->tabwidth[i] = ceil_at_intervals(t->tabwidth[i], rulewidth);
 | 
						|
 | 
						|
    renderCoTable(t, h_env->limit);
 | 
						|
 | 
						|
    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, h_env->limit);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    check_minimum_width(t, t->tabwidth);
 | 
						|
    t->total_width = 0;
 | 
						|
    for (i = 0; i <= t->maxcol; i++) {
 | 
						|
	t->tabwidth[i] = ceil_at_intervals(t->tabwidth[i], rulewidth);
 | 
						|
	t->total_width += t->tabwidth[i];
 | 
						|
    }
 | 
						|
 | 
						|
    t->total_width += table_border_width(t);
 | 
						|
 | 
						|
    check_table_height(t);
 | 
						|
 | 
						|
    for (i = 0; i <= t->maxcol; i++) {
 | 
						|
	for (j = 0; j <= t->maxrow; j++) {
 | 
						|
	    TextLineList *l;
 | 
						|
	    int k;
 | 
						|
	    if ((t->tabattr[j][i] & HTT_Y) ||
 | 
						|
		(t->tabattr[j][i] & HTT_TOP) || (t->tabdata[j][i] == NULL))
 | 
						|
		continue;
 | 
						|
	    h = t->tabheight[j];
 | 
						|
	    for (k = j + 1; k <= t->maxrow; k++) {
 | 
						|
		if (!(t->tabattr[k][i] & HTT_Y))
 | 
						|
		    break;
 | 
						|
		h += t->tabheight[k];
 | 
						|
		switch (t->border_mode) {
 | 
						|
		case BORDER_THIN:
 | 
						|
		case BORDER_THICK:
 | 
						|
		case BORDER_NOWIN:
 | 
						|
		    h += 1;
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    h -= t->tabdata[j][i]->nitem;
 | 
						|
	    if (t->tabattr[j][i] & HTT_MIDDLE)
 | 
						|
		h /= 2;
 | 
						|
	    if (h <= 0)
 | 
						|
		continue;
 | 
						|
	    l = newTextLineList();
 | 
						|
	    for (k = 0; k < h; k++)
 | 
						|
		pushTextLine(l, newTextLine(NULL, 0));
 | 
						|
	    t->tabdata[j][i] = appendGeneralList((GeneralList *)l,
 | 
						|
						 t->tabdata[j][i]);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* table output */
 | 
						|
    width = t->total_width;
 | 
						|
 | 
						|
    make_caption(t, h_env);
 | 
						|
 | 
						|
    HTMLlineproc1("<pre for_table>", h_env);
 | 
						|
#ifdef ID_EXT
 | 
						|
    if (t->id != NULL) {
 | 
						|
	idtag = Sprintf("<_id id=\"%s\">", html_quote((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);
 | 
						|
	push_render_image(renderbuf, width, t->total_width, h_env);
 | 
						|
	t->total_height += 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 ? "\263" : 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\">",
 | 
						|
				html_quote((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\">",
 | 
						|
				    html_quote((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);
 | 
						|
		t->total_height += 1;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    push_render_image(renderbuf, width, t->total_width, h_env);
 | 
						|
	}
 | 
						|
	if (r < t->maxrow && t->border_mode != BORDER_NONE) {
 | 
						|
	    renderbuf = Strnew();
 | 
						|
	    print_sep(t, r, T_MIDDLE, t->maxcol, renderbuf);
 | 
						|
	    push_render_image(renderbuf, width, t->total_width, h_env);
 | 
						|
	}
 | 
						|
	t->total_height += t->tabheight[r];
 | 
						|
    }
 | 
						|
    switch (t->border_mode) {
 | 
						|
    case BORDER_THIN:
 | 
						|
    case BORDER_THICK:
 | 
						|
	renderbuf = Strnew();
 | 
						|
	print_sep(t, t->maxrow, T_BOTTOM, t->maxcol, renderbuf);
 | 
						|
	push_render_image(renderbuf, width, t->total_width, h_env);
 | 
						|
	t->total_height += 1;
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    if (t->total_height == 0) {
 | 
						|
	renderbuf = Strnew(" ");
 | 
						|
	t->total_height++;
 | 
						|
	t->total_width = 1;
 | 
						|
	push_render_image(renderbuf, 1, t->total_width, h_env);
 | 
						|
    }
 | 
						|
    HTMLlineproc1("</pre>", h_env);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TABLE_NO_COMPACT
 | 
						|
#define THR_PADDING 2
 | 
						|
#else
 | 
						|
#define THR_PADDING 4
 | 
						|
#endif
 | 
						|
 | 
						|
struct table *
 | 
						|
begin_table(int border, int spacing, int padding, int vspace)
 | 
						|
{
 | 
						|
    struct table *t;
 | 
						|
    int mincell = minimum_cellspacing(border);
 | 
						|
    int rcellspacing;
 | 
						|
    int mincell_pixels = round(mincell * pixel_per_char);
 | 
						|
    int ppc = round(pixel_per_char);
 | 
						|
 | 
						|
    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;
 | 
						|
 | 
						|
    rcellspacing = spacing + 2 * padding;
 | 
						|
    switch (border) {
 | 
						|
    case BORDER_THIN:
 | 
						|
    case BORDER_THICK:
 | 
						|
    case BORDER_NOWIN:
 | 
						|
	t->cellpadding = padding - (mincell_pixels - 4) / 2;
 | 
						|
	break;
 | 
						|
    case BORDER_NONE:
 | 
						|
	t->cellpadding = rcellspacing - mincell_pixels;
 | 
						|
    }
 | 
						|
    if (t->cellpadding >= ppc)
 | 
						|
	t->cellpadding /= ppc;
 | 
						|
    else if (t->cellpadding > 0)
 | 
						|
	t->cellpadding = 1;
 | 
						|
    else
 | 
						|
	t->cellpadding = 0;
 | 
						|
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    if (border == BORDER_NONE) {
 | 
						|
	if (rcellspacing / 2 + vspace <= 1)
 | 
						|
	    t->vspace = 0;
 | 
						|
	else
 | 
						|
	    t->vspace = 1;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	if (vspace < ppc)
 | 
						|
	    t->vspace = 0;
 | 
						|
	else
 | 
						|
	    t->vspace = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (border == BORDER_NONE) {
 | 
						|
	if (rcellspacing <= THR_PADDING)
 | 
						|
	    t->vcellpadding = 0;
 | 
						|
	else
 | 
						|
	    t->vcellpadding = 1;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	if (padding < 2 * ppc - 2)
 | 
						|
	    t->vcellpadding = 0;
 | 
						|
	else
 | 
						|
	    t->vcellpadding = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return t;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
end_table(struct table *tbl)
 | 
						|
{
 | 
						|
    struct table_cell *cell = &tbl->cell;
 | 
						|
    int i, rulewidth = table_rule_width(tbl);
 | 
						|
    if (rulewidth > 1) {
 | 
						|
	if (tbl->total_width > 0)
 | 
						|
	    tbl->total_width = ceil_at_intervals(tbl->total_width, rulewidth);
 | 
						|
	for (i = 0; i <= tbl->maxcol; i++) {
 | 
						|
	    tbl->minimum_width[i] =
 | 
						|
		ceil_at_intervals(tbl->minimum_width[i], rulewidth);
 | 
						|
	    tbl->tabwidth[i] = ceil_at_intervals(tbl->tabwidth[i], rulewidth);
 | 
						|
	    if (tbl->fixed_width[i] > 0)
 | 
						|
		tbl->fixed_width[i] =
 | 
						|
		    ceil_at_intervals(tbl->fixed_width[i], rulewidth);
 | 
						|
	}
 | 
						|
	for (i = 0; i <= cell->maxcell; i++) {
 | 
						|
	    cell->minimum_width[i] =
 | 
						|
		ceil_at_intervals(cell->minimum_width[i], rulewidth);
 | 
						|
	    cell->width[i] = ceil_at_intervals(cell->width[i], rulewidth);
 | 
						|
	    if (cell->fixed_width[i] > 0)
 | 
						|
		cell->fixed_width[i] =
 | 
						|
		    ceil_at_intervals(cell->fixed_width[i], rulewidth);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    tbl->sloppy_width = fixed_table_width(tbl);
 | 
						|
    if (tbl->total_width > tbl->sloppy_width)
 | 
						|
	tbl->sloppy_width = tbl->total_width;
 | 
						|
}
 | 
						|
 | 
						|
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 table_close_anchor0(struct table *tbl, struct table_mode *mode);
 | 
						|
 | 
						|
static void
 | 
						|
clearcontentssize(struct table *t, struct table_mode *mode)
 | 
						|
{
 | 
						|
    table_close_anchor0(t, mode);
 | 
						|
    mode->nobr_offset = 0;
 | 
						|
    t->linfo.prev_spaces = -1;
 | 
						|
    t->linfo.prevchar = ' ';
 | 
						|
    t->linfo.prev_ctype = PC_ASCII;
 | 
						|
    t->linfo.length = 0;
 | 
						|
    t->tabcontentssize = 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
begin_cell(struct table *t, struct table_mode *mode)
 | 
						|
{
 | 
						|
    clearcontentssize(t, mode);
 | 
						|
    mode->indent_level = 0;
 | 
						|
    mode->nobr_level = 0;
 | 
						|
    mode->pre_mode = 0;
 | 
						|
    t->indent = 0;
 | 
						|
    t->flag |= TBL_IN_COL;
 | 
						|
 | 
						|
    if (t->suspended_data) {
 | 
						|
	check_row(t, t->row);
 | 
						|
	if (t->tabdata[t->row][t->col] == NULL)
 | 
						|
	    t->tabdata[t->row][t->col] = newGeneralList();
 | 
						|
	appendGeneralList(t->tabdata[t->row][t->col],
 | 
						|
			  (GeneralList *)t->suspended_data);
 | 
						|
	t->suspended_data = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
check_rowcol(struct table *tbl, struct table_mode *mode)
 | 
						|
{
 | 
						|
    int row = tbl->row, col = tbl->col;
 | 
						|
 | 
						|
    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;
 | 
						|
 | 
						|
    if (tbl->row != row || tbl->col != col)
 | 
						|
	begin_cell(tbl, mode);
 | 
						|
    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, prev_ctype = linfo->prev_ctype;
 | 
						|
    int prevchar = linfo->prevchar;
 | 
						|
    int w = linfo->length;
 | 
						|
    int min = 1;
 | 
						|
 | 
						|
    if (*line == '<' && line[strlen(line) - 1] == '>') {
 | 
						|
	if (checkminimum)
 | 
						|
	    check_minimum0(t, visible_length(line));
 | 
						|
	return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    while (*line) {
 | 
						|
	char *save = line;
 | 
						|
	int ec = '\0', len, wlen, c;
 | 
						|
	ctype = get_mctype(line);
 | 
						|
	wlen = len = get_mclen(ctype);
 | 
						|
	c = mctowc(line, ctype);
 | 
						|
	if (min < w)
 | 
						|
	    min = w;
 | 
						|
	if (ctype == PC_ASCII && IS_SPACE(c)) {
 | 
						|
	    w = 0;
 | 
						|
	    s++;
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (c == '&') {
 | 
						|
		ec = getescapechar(&line);
 | 
						|
		if (ec >= 0) {
 | 
						|
		    c = ec;
 | 
						|
		    ctype = IS_CNTRL(ec) ? PC_CTRL : PC_ASCII;
 | 
						|
		    len = strlen(conv_entity(ec));
 | 
						|
		    wlen = line - save;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    if (prevchar && is_boundary(prevchar, c)) {
 | 
						|
		w = len;
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		w += len;
 | 
						|
	    }
 | 
						|
	    if (s > 0) {
 | 
						|
#ifdef JP_CHARSET
 | 
						|
		if (ctype == PC_KANJI && prev_ctype == PC_KANJI)
 | 
						|
		    skip += s;
 | 
						|
		else
 | 
						|
#endif				/* JP_CHARSET */
 | 
						|
		    skip += s - 1;
 | 
						|
	    }
 | 
						|
	    s = 0;
 | 
						|
	    prev_ctype = ctype;
 | 
						|
	}
 | 
						|
	prevchar = c;
 | 
						|
	line = save + wlen;
 | 
						|
    }
 | 
						|
    if (s > 1) {
 | 
						|
	skip += s - 1;
 | 
						|
	linfo->prev_spaces = 1;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	linfo->prev_spaces = s;
 | 
						|
    }
 | 
						|
    linfo->prev_ctype = prev_ctype;
 | 
						|
    linfo->prevchar = prevchar;
 | 
						|
 | 
						|
    if (checkminimum) {
 | 
						|
	if (min < w)
 | 
						|
	    min = w;
 | 
						|
	linfo->length = w;
 | 
						|
	check_minimum0(t, min);
 | 
						|
    }
 | 
						|
    return skip;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
feed_table_inline_tag(struct table *tbl,
 | 
						|
		      char *line, struct table_mode *mode, int width)
 | 
						|
{
 | 
						|
    check_rowcol(tbl, mode);
 | 
						|
    pushdata(tbl, tbl->row, tbl->col, line);
 | 
						|
    if (width >= 0) {
 | 
						|
	check_minimum0(tbl, width);
 | 
						|
	addcontentssize(tbl, width);
 | 
						|
	setwidth(tbl, mode);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
feed_table_block_tag(struct table *tbl,
 | 
						|
		     char *line, struct table_mode *mode, int indent, int cmd)
 | 
						|
{
 | 
						|
    int offset;
 | 
						|
    if (mode->indent_level <= 0 && indent == -1)
 | 
						|
	return;
 | 
						|
    setwidth(tbl, mode);
 | 
						|
    feed_table_inline_tag(tbl, line, mode, -1);
 | 
						|
    clearcontentssize(tbl, mode);
 | 
						|
    if (indent == 1) {
 | 
						|
	mode->indent_level++;
 | 
						|
	if (mode->indent_level <= MAX_INDENT_LEVEL)
 | 
						|
	    tbl->indent += INDENT_INCR;
 | 
						|
    }
 | 
						|
    else if (indent == -1) {
 | 
						|
	mode->indent_level--;
 | 
						|
	if (mode->indent_level < MAX_INDENT_LEVEL)
 | 
						|
	    tbl->indent -= INDENT_INCR;
 | 
						|
    }
 | 
						|
    offset = tbl->indent;
 | 
						|
    if (cmd == HTML_DT) {
 | 
						|
	if (mode->indent_level > 0 && mode->indent_level <= MAX_INDENT_LEVEL)
 | 
						|
	    offset -= INDENT_INCR;
 | 
						|
    }
 | 
						|
    if (tbl->indent > 0) {
 | 
						|
	check_minimum0(tbl, 0);
 | 
						|
	addcontentssize(tbl, offset);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
table_close_select(struct table *tbl, struct table_mode *mode, int width)
 | 
						|
{
 | 
						|
    Str tmp = process_n_select();
 | 
						|
    mode->pre_mode &= ~TBLM_INSELECT;
 | 
						|
    mode->end_tag = 0;
 | 
						|
    feed_table1(tbl, tmp, mode, width);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
table_close_textarea(struct table *tbl, struct table_mode *mode, int width)
 | 
						|
{
 | 
						|
    Str tmp = process_n_textarea();
 | 
						|
    mode->pre_mode &= ~TBLM_INTXTA;
 | 
						|
    mode->end_tag = 0;
 | 
						|
    feed_table1(tbl, tmp, mode, width);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
table_close_anchor0(struct table *tbl, struct table_mode *mode)
 | 
						|
{
 | 
						|
    if (!(mode->pre_mode & TBLM_ANCHOR))
 | 
						|
	return;
 | 
						|
    mode->pre_mode &= ~TBLM_ANCHOR;
 | 
						|
    if (tbl->tabcontentssize == mode->anchor_offset) {
 | 
						|
	check_minimum0(tbl, 1);
 | 
						|
	addcontentssize(tbl, 1);
 | 
						|
	setwidth(tbl, mode);
 | 
						|
    }
 | 
						|
    else if (tbl->linfo.prev_spaces > 0 &&
 | 
						|
	     tbl->tabcontentssize - 1 == mode->anchor_offset) {
 | 
						|
	if (tbl->linfo.prev_spaces > 0)
 | 
						|
	    tbl->linfo.prev_spaces = -1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#define TAG_ACTION_NONE 0
 | 
						|
#define TAG_ACTION_FEED 1
 | 
						|
#define TAG_ACTION_TABLE 2
 | 
						|
#define TAG_ACTION_N_TABLE 3
 | 
						|
#define TAG_ACTION_PLAIN 4
 | 
						|
 | 
						|
#define CASE_TABLE_TAG \
 | 
						|
	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
 | 
						|
 | 
						|
static int
 | 
						|
feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
 | 
						|
	       int width, struct parsed_tag *tag)
 | 
						|
{
 | 
						|
    int cmd;
 | 
						|
    char *p;
 | 
						|
    struct table_cell *cell = &tbl->cell;
 | 
						|
    int colspan, rowspan;
 | 
						|
    int col, prev_col;
 | 
						|
    int i, j, k, v, v0, w, id;
 | 
						|
    Str tok, tmp, anchor;
 | 
						|
    table_attr align, valign;
 | 
						|
 | 
						|
    cmd = tag->tagid;
 | 
						|
 | 
						|
    if (mode->pre_mode & TBLM_PLAIN) {
 | 
						|
	if (mode->end_tag == cmd) {
 | 
						|
	    mode->pre_mode &= ~TBLM_PLAIN;
 | 
						|
	    mode->end_tag = 0;
 | 
						|
	    feed_table_block_tag(tbl, line, mode, 0, cmd);
 | 
						|
	    return TAG_ACTION_NONE;
 | 
						|
	}
 | 
						|
	return TAG_ACTION_PLAIN;
 | 
						|
    }
 | 
						|
    if (mode->pre_mode & TBLM_INTXTA) {
 | 
						|
	if (mode->end_tag == cmd) {
 | 
						|
	    table_close_textarea(tbl, mode, width);
 | 
						|
	    return TAG_ACTION_NONE;
 | 
						|
	}
 | 
						|
	return TAG_ACTION_FEED;
 | 
						|
    }
 | 
						|
    if (mode->pre_mode & TBLM_SCRIPT) {
 | 
						|
	if (mode->end_tag == cmd) {
 | 
						|
	    mode->pre_mode &= ~TBLM_SCRIPT;
 | 
						|
	    mode->end_tag = 0;
 | 
						|
	    return TAG_ACTION_NONE;
 | 
						|
	}
 | 
						|
	return TAG_ACTION_PLAIN;
 | 
						|
    }
 | 
						|
    if (mode->pre_mode & TBLM_STYLE) {
 | 
						|
	if (mode->end_tag == cmd) {
 | 
						|
	    mode->pre_mode &= ~TBLM_STYLE;
 | 
						|
	    mode->end_tag = 0;
 | 
						|
	    return TAG_ACTION_NONE;
 | 
						|
	}
 | 
						|
	return TAG_ACTION_PLAIN;
 | 
						|
    }
 | 
						|
    /* 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_TABLE_TAG:
 | 
						|
	case HTML_N_FORM:
 | 
						|
	case HTML_N_SELECT:	/* mode->end_tag */
 | 
						|
	    table_close_select(tbl, mode, width);
 | 
						|
	    if (cmd == HTML_N_SELECT)
 | 
						|
		return TAG_ACTION_NONE;
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	    return TAG_ACTION_FEED;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (mode->caption) {
 | 
						|
	switch (cmd) {
 | 
						|
	  CASE_TABLE_TAG:
 | 
						|
	case HTML_N_CAPTION:
 | 
						|
	    mode->caption = 0;
 | 
						|
	    if (cmd == HTML_N_CAPTION)
 | 
						|
		return TAG_ACTION_NONE;
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	    return TAG_ACTION_FEED;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (mode->pre_mode & TBLM_PRE) {
 | 
						|
	switch (cmd) {
 | 
						|
	case HTML_NOBR:
 | 
						|
	case HTML_N_NOBR:
 | 
						|
	case HTML_PRE_INT:
 | 
						|
	case HTML_N_PRE_INT:
 | 
						|
	    return TAG_ACTION_NONE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    switch (cmd) {
 | 
						|
    case HTML_TABLE:
 | 
						|
	check_rowcol(tbl, mode);
 | 
						|
	return TAG_ACTION_TABLE;
 | 
						|
    case HTML_N_TABLE:
 | 
						|
	if (tbl->suspended_data)
 | 
						|
	    check_rowcol(tbl, mode);
 | 
						|
	return TAG_ACTION_N_TABLE;
 | 
						|
    case HTML_TR:
 | 
						|
	if (tbl->col >= 0 && tbl->tabcontentssize > 0)
 | 
						|
	    setwidth(tbl, mode);
 | 
						|
	tbl->col = -1;
 | 
						|
	tbl->row++;
 | 
						|
	tbl->flag |= TBL_IN_ROW;
 | 
						|
	tbl->flag &= ~TBL_IN_COL;
 | 
						|
	align = 0;
 | 
						|
	valign = 0;
 | 
						|
	if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
 | 
						|
	    switch (i) {
 | 
						|
	    case ALIGN_LEFT:
 | 
						|
		align = (HTT_LEFT | HTT_TRSET);
 | 
						|
		break;
 | 
						|
	    case ALIGN_RIGHT:
 | 
						|
		align = (HTT_RIGHT | HTT_TRSET);
 | 
						|
		break;
 | 
						|
	    case ALIGN_CENTER:
 | 
						|
		align = (HTT_CENTER | HTT_TRSET);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
 | 
						|
	    switch (i) {
 | 
						|
	    case VALIGN_TOP:
 | 
						|
		valign = (HTT_TOP | HTT_VTRSET);
 | 
						|
		break;
 | 
						|
	    case VALIGN_MIDDLE:
 | 
						|
		valign = (HTT_MIDDLE | HTT_VTRSET);
 | 
						|
		break;
 | 
						|
	    case VALIGN_BOTTOM:
 | 
						|
		valign = (HTT_BOTTOM | HTT_VTRSET);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
#ifdef ID_EXT
 | 
						|
	if (parsedtag_get_value(tag, ATTR_ID, &p))
 | 
						|
	    tbl->tridvalue[tbl->row] = Strnew_charp(p);
 | 
						|
#endif				/* ID_EXT */
 | 
						|
	tbl->trattr = align | valign;
 | 
						|
	break;
 | 
						|
    case HTML_TH:
 | 
						|
    case HTML_TD:
 | 
						|
	prev_col = tbl->col;
 | 
						|
	if (tbl->col >= 0 && tbl->tabcontentssize > 0)
 | 
						|
	    setwidth(tbl, mode);
 | 
						|
	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;
 | 
						|
	}
 | 
						|
	colspan = rowspan = 1;
 | 
						|
	if (tbl->trattr & HTT_TRSET)
 | 
						|
	    align = (tbl->trattr & HTT_ALIGN);
 | 
						|
	else if (cmd == HTML_TH)
 | 
						|
	    align = HTT_CENTER;
 | 
						|
	else
 | 
						|
	    align = HTT_LEFT;
 | 
						|
	if (tbl->trattr & HTT_VTRSET)
 | 
						|
	    valign = (tbl->trattr & HTT_VALIGN);
 | 
						|
	else
 | 
						|
	    valign = HTT_MIDDLE;
 | 
						|
	if (parsedtag_get_value(tag, ATTR_ROWSPAN, &rowspan)) {
 | 
						|
	    if ((tbl->row + rowspan) >= tbl->max_rowsize)
 | 
						|
		check_row(tbl, tbl->row + rowspan);
 | 
						|
	}
 | 
						|
	if (parsedtag_get_value(tag, ATTR_COLSPAN, &colspan)) {
 | 
						|
	    if ((tbl->col + colspan) >= MAXCOL) {
 | 
						|
		/* Can't expand column */
 | 
						|
		colspan = MAXCOL - tbl->col;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
 | 
						|
	    switch (i) {
 | 
						|
	    case ALIGN_LEFT:
 | 
						|
		align = HTT_LEFT;
 | 
						|
		break;
 | 
						|
	    case ALIGN_RIGHT:
 | 
						|
		align = HTT_RIGHT;
 | 
						|
		break;
 | 
						|
	    case ALIGN_CENTER:
 | 
						|
		align = HTT_CENTER;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
 | 
						|
	    switch (i) {
 | 
						|
	    case VALIGN_TOP:
 | 
						|
		valign = HTT_TOP;
 | 
						|
		break;
 | 
						|
	    case VALIGN_MIDDLE:
 | 
						|
		valign = HTT_MIDDLE;
 | 
						|
		break;
 | 
						|
	    case VALIGN_BOTTOM:
 | 
						|
		valign = HTT_BOTTOM;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
#ifdef NOWRAP
 | 
						|
	if (parsedtag_exists(tag, ATTR_NOWRAP))
 | 
						|
	    tbl->tabattr[tbl->row][tbl->col] |= HTT_NOWRAP;
 | 
						|
#endif				/* NOWRAP */
 | 
						|
	v = 0;
 | 
						|
	if (parsedtag_get_value(tag, ATTR_WIDTH, &v)) {
 | 
						|
#ifdef TABLE_EXPAND
 | 
						|
	    if (v > 0) {
 | 
						|
		if (tbl->real_width > 0)
 | 
						|
		    v = -(v * 100) / (tbl->real_width * pixel_per_char);
 | 
						|
		else
 | 
						|
		    v = (int)(v / pixel_per_char);
 | 
						|
	    }
 | 
						|
#else
 | 
						|
	    v = RELATIVE_WIDTH(v);
 | 
						|
#endif				/* not TABLE_EXPAND */
 | 
						|
	}
 | 
						|
#ifdef ID_EXT
 | 
						|
	if (parsedtag_get_value(tag, ATTR_ID, &p))
 | 
						|
	    tbl->tabidvalue[tbl->row][tbl->col] = Strnew_charp(p);
 | 
						|
#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 | HTT_VALIGN);
 | 
						|
	tbl->tabattr[tbl->row][tbl->col] |= (align | valign);
 | 
						|
	if (colspan > 1) {
 | 
						|
	    col = tbl->col;
 | 
						|
 | 
						|
	    cell->icell = cell->maxcell + 1;
 | 
						|
	    k = bsearch_2short(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) {
 | 
						|
		    int ii;
 | 
						|
		    for (ii = k; ii < cell->maxcell; ii++)
 | 
						|
			cell->index[ii + 1] = cell->index[ii];
 | 
						|
		}
 | 
						|
		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 FEED_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++) {
 | 
						|
#if 0
 | 
						|
		tbl->tabattr[tbl->row + i][tbl->col + j] &= ~(HTT_X | HTT_Y);
 | 
						|
#endif
 | 
						|
		if (!(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;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	begin_cell(tbl, mode);
 | 
						|
	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 FEED_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 = ((TextList *)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:
 | 
						|
    case HTML_LI:
 | 
						|
    case HTML_PRE:
 | 
						|
    case HTML_N_PRE:
 | 
						|
    case HTML_HR:
 | 
						|
    case HTML_LISTING:
 | 
						|
    case HTML_XMP:
 | 
						|
    case HTML_PLAINTEXT:
 | 
						|
    case HTML_PRE_PLAIN:
 | 
						|
    case HTML_N_PRE_PLAIN:
 | 
						|
	feed_table_block_tag(tbl, line, mode, 0, cmd);
 | 
						|
	switch (cmd) {
 | 
						|
	case HTML_PRE:
 | 
						|
	case HTML_PRE_PLAIN:
 | 
						|
	    mode->pre_mode |= TBLM_PRE;
 | 
						|
	    break;
 | 
						|
	case HTML_N_PRE:
 | 
						|
	case HTML_N_PRE_PLAIN:
 | 
						|
	    mode->pre_mode &= ~TBLM_PRE;
 | 
						|
	    break;
 | 
						|
	case HTML_LISTING:
 | 
						|
	    mode->pre_mode |= TBLM_PLAIN;
 | 
						|
	    mode->end_tag = HTML_N_LISTING;
 | 
						|
	    break;
 | 
						|
	case HTML_XMP:
 | 
						|
	    mode->pre_mode |= TBLM_PLAIN;
 | 
						|
	    mode->end_tag = HTML_N_XMP;
 | 
						|
	    break;
 | 
						|
	case HTML_PLAINTEXT:
 | 
						|
	    mode->pre_mode |= TBLM_PLAIN;
 | 
						|
	    mode->end_tag = MAX_HTMLTAG;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    case HTML_DL:
 | 
						|
    case HTML_BLQ:
 | 
						|
    case HTML_OL:
 | 
						|
    case HTML_UL:
 | 
						|
	feed_table_block_tag(tbl, line, mode, 1, cmd);
 | 
						|
	break;
 | 
						|
    case HTML_N_DL:
 | 
						|
    case HTML_N_BLQ:
 | 
						|
    case HTML_N_OL:
 | 
						|
    case HTML_N_UL:
 | 
						|
	feed_table_block_tag(tbl, line, mode, -1, cmd);
 | 
						|
	break;
 | 
						|
    case HTML_PRE_INT:
 | 
						|
    case HTML_NOBR:
 | 
						|
    case HTML_WBR:
 | 
						|
	feed_table_inline_tag(tbl, line, mode, -1);
 | 
						|
	switch (cmd) {
 | 
						|
	case HTML_NOBR:
 | 
						|
	    mode->nobr_level++;
 | 
						|
	    if (mode->pre_mode & TBLM_NOBR)
 | 
						|
		return TAG_ACTION_NONE;
 | 
						|
	    mode->pre_mode |= TBLM_NOBR;
 | 
						|
	    break;
 | 
						|
	case HTML_PRE_INT:
 | 
						|
	    if (mode->pre_mode & TBLM_PRE_INT)
 | 
						|
		return TAG_ACTION_NONE;
 | 
						|
	    mode->pre_mode |= TBLM_PRE_INT;
 | 
						|
	    tbl->linfo.prev_spaces = 0;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	mode->nobr_offset = -1;
 | 
						|
	if (tbl->linfo.length > 0) {
 | 
						|
	    check_minimum0(tbl, tbl->linfo.length);
 | 
						|
	    tbl->linfo.length = 0;
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    case HTML_N_NOBR:
 | 
						|
	feed_table_inline_tag(tbl, line, mode, -1);
 | 
						|
	if (mode->nobr_level > 0)
 | 
						|
	    mode->nobr_level--;
 | 
						|
	if (mode->nobr_level == 0)
 | 
						|
	    mode->pre_mode &= ~TBLM_NOBR;
 | 
						|
	break;
 | 
						|
    case HTML_N_PRE_INT:
 | 
						|
	feed_table_inline_tag(tbl, line, mode, -1);
 | 
						|
	mode->pre_mode &= ~TBLM_PRE_INT;
 | 
						|
	break;
 | 
						|
    case HTML_IMG:
 | 
						|
	w = tbl->fixed_width[tbl->col];
 | 
						|
	if (w < 0) {
 | 
						|
	    if (tbl->total_width > 0)
 | 
						|
		w = -tbl->total_width * w / 100;
 | 
						|
	    else if (width > 0)
 | 
						|
		w = -width * w / 100;
 | 
						|
	    else
 | 
						|
		w = 0;
 | 
						|
	}
 | 
						|
	else if (w == 0) {
 | 
						|
	    if (tbl->total_width > 0)
 | 
						|
		w = tbl->total_width;
 | 
						|
	    else if (width > 0)
 | 
						|
		w = width;
 | 
						|
	}
 | 
						|
	tok = process_img(tag, w);
 | 
						|
	feed_table1(tbl, tok, mode, width);
 | 
						|
	break;
 | 
						|
    case HTML_FORM:
 | 
						|
	feed_table_block_tag(tbl, "", mode, 0, cmd);
 | 
						|
	tmp = process_form(tag);
 | 
						|
	if (tmp)
 | 
						|
	    feed_table1(tbl, tmp, mode, width);
 | 
						|
	break;
 | 
						|
    case HTML_N_FORM:
 | 
						|
	feed_table_block_tag(tbl, "", mode, 0, cmd);
 | 
						|
	process_n_form();
 | 
						|
	break;
 | 
						|
    case HTML_INPUT:
 | 
						|
	tmp = process_input(tag);
 | 
						|
	feed_table1(tbl, tmp, mode, width);
 | 
						|
	break;
 | 
						|
    case HTML_SELECT:
 | 
						|
	tmp = process_select(tag);
 | 
						|
	if (tmp)
 | 
						|
	    feed_table1(tbl, tmp, mode, width);
 | 
						|
	mode->pre_mode |= TBLM_INSELECT;
 | 
						|
	mode->end_tag = HTML_N_SELECT;
 | 
						|
	break;
 | 
						|
    case HTML_N_SELECT:
 | 
						|
    case HTML_OPTION:
 | 
						|
	/* nothing */
 | 
						|
	break;
 | 
						|
    case HTML_TEXTAREA:
 | 
						|
	w = 0;
 | 
						|
	check_rowcol(tbl, mode);
 | 
						|
	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(tag, w);
 | 
						|
	if (tmp)
 | 
						|
	    feed_table1(tbl, tmp, mode, width);
 | 
						|
	mode->pre_mode |= TBLM_INTXTA;
 | 
						|
	mode->end_tag = HTML_N_TEXTAREA;
 | 
						|
	break;
 | 
						|
    case HTML_A:
 | 
						|
	table_close_anchor0(tbl, mode);
 | 
						|
	anchor = NULL;
 | 
						|
	i = 0;
 | 
						|
	parsedtag_get_value(tag, ATTR_HREF, &anchor);
 | 
						|
	parsedtag_get_value(tag, ATTR_HSEQ, &i);
 | 
						|
	if (anchor) {
 | 
						|
	    check_rowcol(tbl, mode);
 | 
						|
	    if (i == 0) {
 | 
						|
		Str tmp = process_anchor(tag, line);
 | 
						|
		pushdata(tbl, tbl->row, tbl->col, tmp->ptr);
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
		pushdata(tbl, tbl->row, tbl->col, line);
 | 
						|
	    if (i >= 0) {
 | 
						|
		mode->pre_mode |= TBLM_ANCHOR;
 | 
						|
		mode->anchor_offset = tbl->tabcontentssize;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    suspend_or_pushdata(tbl, line);
 | 
						|
	break;
 | 
						|
    case HTML_DEL:
 | 
						|
	if (displayInsDel)
 | 
						|
	    feed_table_inline_tag(tbl, line, mode, 5);	/* [DEL: */
 | 
						|
	else
 | 
						|
	    mode->pre_mode |= TBLM_DEL;
 | 
						|
	break;
 | 
						|
    case HTML_N_DEL:
 | 
						|
	if (displayInsDel)
 | 
						|
	    feed_table_inline_tag(tbl, line, mode, 5);	/* :DEL] */
 | 
						|
	else
 | 
						|
	    mode->pre_mode &= ~TBLM_DEL;
 | 
						|
	break;
 | 
						|
    case HTML_S:
 | 
						|
	if (displayInsDel)
 | 
						|
	    feed_table_inline_tag(tbl, line, mode, 3);	/* [S: */
 | 
						|
	else
 | 
						|
	    mode->pre_mode |= TBLM_S;
 | 
						|
	break;
 | 
						|
    case HTML_N_S:
 | 
						|
	if (displayInsDel)
 | 
						|
	    feed_table_inline_tag(tbl, line, mode, 3);	/* :S] */
 | 
						|
	else
 | 
						|
	    mode->pre_mode &= ~TBLM_S;
 | 
						|
	break;
 | 
						|
    case HTML_INS:
 | 
						|
    case HTML_N_INS:
 | 
						|
	if (displayInsDel)
 | 
						|
	    feed_table_inline_tag(tbl, line, mode, 5);	/* [INS:, :INS] */
 | 
						|
	break;
 | 
						|
    case HTML_SUP:
 | 
						|
    case HTML_SUB:
 | 
						|
    case HTML_N_SUB:
 | 
						|
	if (!(mode->pre_mode & (TBLM_DEL | TBLM_S)))
 | 
						|
	    feed_table_inline_tag(tbl, line, mode, 1);	/* ^, [, ] */
 | 
						|
	break;
 | 
						|
    case HTML_N_SUP:
 | 
						|
	break;
 | 
						|
    case HTML_TABLE_ALT:
 | 
						|
	id = -1;
 | 
						|
	w = 0;
 | 
						|
	parsedtag_get_value(tag, ATTR_TID, &id);
 | 
						|
	if (id >= 0 && id < tbl->ntable) {
 | 
						|
	    struct table *tbl1 = tbl->tables[id].ptr;
 | 
						|
	    feed_table_block_tag(tbl, line, mode, 0, cmd);
 | 
						|
	    addcontentssize(tbl, maximum_table_width(tbl1));
 | 
						|
	    check_minimum0(tbl, tbl1->sloppy_width);
 | 
						|
#ifdef TABLE_EXPAND
 | 
						|
	    w = tbl1->total_width;
 | 
						|
	    v = 0;
 | 
						|
	    colspan = table_colspan(tbl, tbl->row, tbl->col);
 | 
						|
	    if (colspan > 1) {
 | 
						|
		if (cell->icell >= 0)
 | 
						|
		    v = cell->fixed_width[cell->icell];
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
		v = tbl->fixed_width[tbl->col];
 | 
						|
	    if (v < 0 && tbl->real_width > 0 && tbl1->real_width > 0)
 | 
						|
		w = -(tbl1->real_width * 100) / tbl->real_width;
 | 
						|
	    else
 | 
						|
		w = tbl1->real_width;
 | 
						|
	    if (w > 0)
 | 
						|
		check_minimum0(tbl, w);
 | 
						|
	    else if (w < 0 && v < w) {
 | 
						|
		if (colspan > 1) {
 | 
						|
		    if (cell->icell >= 0)
 | 
						|
			cell->fixed_width[cell->icell] = w;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		    tbl->fixed_width[tbl->col] = w;
 | 
						|
	    }
 | 
						|
#endif
 | 
						|
	    setwidth0(tbl, mode);
 | 
						|
	    clearcontentssize(tbl, mode);
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    case HTML_CAPTION:
 | 
						|
	mode->caption = 1;
 | 
						|
	break;
 | 
						|
    case HTML_N_CAPTION:
 | 
						|
    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;
 | 
						|
	mode->end_tag = HTML_N_SCRIPT;
 | 
						|
	break;
 | 
						|
    case HTML_STYLE:
 | 
						|
	mode->pre_mode |= TBLM_STYLE;
 | 
						|
	mode->end_tag = HTML_N_STYLE;
 | 
						|
	break;
 | 
						|
    case HTML_N_A:
 | 
						|
	table_close_anchor0(tbl, mode);
 | 
						|
    case HTML_FONT:
 | 
						|
    case HTML_N_FONT:
 | 
						|
    case HTML_NOP:
 | 
						|
	suspend_or_pushdata(tbl, line);
 | 
						|
	break;
 | 
						|
    case HTML_INTERNAL:
 | 
						|
    case HTML_N_INTERNAL:
 | 
						|
    case HTML_FORM_INT:
 | 
						|
    case HTML_N_FORM_INT:
 | 
						|
    case HTML_INPUT_ALT:
 | 
						|
    case HTML_N_INPUT_ALT:
 | 
						|
    case HTML_SELECT_INT:
 | 
						|
    case HTML_N_SELECT_INT:
 | 
						|
    case HTML_OPTION_INT:
 | 
						|
    case HTML_TEXTAREA_INT:
 | 
						|
    case HTML_N_TEXTAREA_INT:
 | 
						|
    case HTML_IMG_ALT:
 | 
						|
    case HTML_RULE:
 | 
						|
    case HTML_N_RULE:
 | 
						|
    default:
 | 
						|
	/* unknown tag: put into table */
 | 
						|
	return TAG_ACTION_FEED;
 | 
						|
    }
 | 
						|
    return TAG_ACTION_NONE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
feed_table(struct table *tbl, char *line, struct table_mode *mode,
 | 
						|
	   int width, int internal)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    char *p;
 | 
						|
    Str tmp;
 | 
						|
    struct table_linfo *linfo = &tbl->linfo;
 | 
						|
 | 
						|
    if (*line == '<' && line[1] && REALLY_THE_BEGINNING_OF_A_TAG(line)) {
 | 
						|
	struct parsed_tag *tag;
 | 
						|
	p = line;
 | 
						|
	tag = parse_tag(&p, internal);
 | 
						|
	if (tag) {
 | 
						|
	    switch (feed_table_tag(tbl, line, mode, width, tag)) {
 | 
						|
	    case TAG_ACTION_NONE:
 | 
						|
		return -1;
 | 
						|
	    case TAG_ACTION_N_TABLE:
 | 
						|
		return 0;
 | 
						|
	    case TAG_ACTION_TABLE:
 | 
						|
		return 1;
 | 
						|
	    case TAG_ACTION_PLAIN:
 | 
						|
		break;
 | 
						|
	    case TAG_ACTION_FEED:
 | 
						|
	    default:
 | 
						|
		if (parsedtag_need_reconstruct(tag))
 | 
						|
		    line = parsedtag2str(tag)->ptr;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    if (!(mode->pre_mode & (TBLM_PLAIN | TBLM_INTXTA | TBLM_INSELECT |
 | 
						|
				    TBLM_SCRIPT | TBLM_STYLE)))
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	if (mode->pre_mode & (TBLM_DEL | TBLM_S))
 | 
						|
	    return -1;
 | 
						|
    }
 | 
						|
    if (mode->caption) {
 | 
						|
	Strcat_charp(tbl->caption, line);
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    if (mode->pre_mode & TBLM_SCRIPT)
 | 
						|
	return -1;
 | 
						|
    if (mode->pre_mode & TBLM_STYLE)
 | 
						|
	return -1;
 | 
						|
    if (mode->pre_mode & TBLM_INTXTA) {
 | 
						|
	feed_textarea(line);
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    if (mode->pre_mode & TBLM_INSELECT) {
 | 
						|
	feed_select(line);
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    if (!(mode->pre_mode & TBLM_PLAIN) &&
 | 
						|
	!(*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 {
 | 
						|
		    int ec;
 | 
						|
		    q = p;
 | 
						|
		    switch (ec = getescapechar(&p)) {
 | 
						|
		    case '<':
 | 
						|
			Strcat_charp(tmp, "<");
 | 
						|
			break;
 | 
						|
		    case '>':
 | 
						|
			Strcat_charp(tmp, ">");
 | 
						|
			break;
 | 
						|
		    case '&':
 | 
						|
			Strcat_charp(tmp, "&");
 | 
						|
			break;
 | 
						|
		    case '\r':
 | 
						|
			Strcat_char(tmp, '\n');
 | 
						|
			break;
 | 
						|
		    default:
 | 
						|
			r = conv_entity(ec);
 | 
						|
			if (r != NULL && strlen(r) == 1 &&
 | 
						|
			    ec == (unsigned char)*r) {
 | 
						|
			    Strcat_char(tmp, *r);
 | 
						|
			    break;
 | 
						|
			}
 | 
						|
		    case -1:
 | 
						|
			Strcat_char(tmp, *q);
 | 
						|
			p = q + 1;
 | 
						|
			break;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		Strcat_char(tmp, *p);
 | 
						|
		p++;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	line = tmp->ptr;
 | 
						|
    }
 | 
						|
    if (!(mode->pre_mode & (TBLM_SPECIAL & ~TBLM_NOBR))) {
 | 
						|
	if (!(tbl->flag & TBL_IN_COL) || linfo->prev_spaces != 0)
 | 
						|
	    while (IS_SPACE(*line))
 | 
						|
		line++;
 | 
						|
	if (*line == '\0')
 | 
						|
	    return -1;
 | 
						|
	check_rowcol(tbl, mode);
 | 
						|
	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);
 | 
						|
	pushdata(tbl, tbl->row, tbl->col, line);
 | 
						|
    }
 | 
						|
    else if (mode->pre_mode & TBLM_PRE_INT) {
 | 
						|
	check_rowcol(tbl, mode);
 | 
						|
	if (mode->nobr_offset < 0)
 | 
						|
	    mode->nobr_offset = tbl->tabcontentssize;
 | 
						|
	addcontentssize(tbl, maximum_visible_length(line));
 | 
						|
	setwidth(tbl, mode);
 | 
						|
	pushdata(tbl, tbl->row, tbl->col, line);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	/* <pre> mode or something like it */
 | 
						|
	check_rowcol(tbl, mode);
 | 
						|
	while (*line) {
 | 
						|
	    int nl = FALSE;
 | 
						|
	    if ((p = strchr(line, '\r')) || (p = strchr(line, '\n'))) {
 | 
						|
		if (*p == '\r' && p[1] == '\n')
 | 
						|
		    p++;
 | 
						|
		if (p[1]) {
 | 
						|
		    p++;
 | 
						|
		    tmp = Strnew_charp_n(line, p - line);
 | 
						|
		    line = p;
 | 
						|
		    p = tmp->ptr;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
		    p = line;
 | 
						|
		    line = "";
 | 
						|
		}
 | 
						|
		nl = TRUE;
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
		p = line;
 | 
						|
		line = "";
 | 
						|
	    }
 | 
						|
	    if (mode->pre_mode & TBLM_PLAIN)
 | 
						|
		i = maximum_visible_length_plain(p);
 | 
						|
	    else
 | 
						|
		i = maximum_visible_length(p);
 | 
						|
	    addcontentssize(tbl, i);
 | 
						|
	    setwidth(tbl, mode);
 | 
						|
	    if (nl)
 | 
						|
		clearcontentssize(tbl, mode);
 | 
						|
	    pushdata(tbl, tbl->row, tbl->col, p);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
feed_table1(struct table *tbl, Str tok, struct table_mode *mode, int width)
 | 
						|
{
 | 
						|
    Str tokbuf;
 | 
						|
    int status;
 | 
						|
    char *line;
 | 
						|
    if (!tok)
 | 
						|
	return;
 | 
						|
    tokbuf = Strnew();
 | 
						|
    status = R_ST_NORMAL;
 | 
						|
    line = tok->ptr;
 | 
						|
    while (read_token
 | 
						|
	   (tokbuf, &line, &status, mode->pre_mode & TBLM_PREMODE, 0))
 | 
						|
	feed_table(tbl, tokbuf->ptr, mode, width, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pushTable(struct table *tbl, struct table *tbl1)
 | 
						|
{
 | 
						|
    int col;
 | 
						|
    int row;
 | 
						|
 | 
						|
    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)
 | 
						|
	    bcopy(tbl->tables, tmp, tbl->ntable * sizeof(struct table_in));
 | 
						|
	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 = newTextLineList();
 | 
						|
    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
 | 
						|
correct_table_matrix4(struct table *t, int col, int cspan, char *flags,
 | 
						|
		      double s, double b)
 | 
						|
{
 | 
						|
    int i, j;
 | 
						|
    double ss;
 | 
						|
    int ecol = col + cspan;
 | 
						|
    int size = t->maxcol + 1;
 | 
						|
    double w = 1. / (b * b);
 | 
						|
 | 
						|
    for (i = 0; i < size; i++) {
 | 
						|
	if (flags[i] && !(i >= col && i < ecol))
 | 
						|
	    continue;
 | 
						|
	for (j = i; j < size; j++) {
 | 
						|
	    if (flags[j] && !(j >= col && j < ecol))
 | 
						|
		continue;
 | 
						|
	    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
 | 
						|
set_table_matrix0(struct table *t, int maxwidth)
 | 
						|
{
 | 
						|
    int size = t->maxcol + 1;
 | 
						|
    int i, j, k, bcol, ecol;
 | 
						|
    int width;
 | 
						|
    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];
 | 
						|
	width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
 | 
						|
	w1 = 0.;
 | 
						|
	for (i = bcol; i < ecol; i++) {
 | 
						|
	    w1 += t->tabwidth[i] + 0.1;
 | 
						|
	    expand[i]++;
 | 
						|
	}
 | 
						|
	for (i = bcol; i < ecol; i++) {
 | 
						|
	    w = weight(width * (t->tabwidth[i] + 0.1) / w1);
 | 
						|
	    if (w > we[i])
 | 
						|
		we[i] = w;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    w0 = 0.;
 | 
						|
    w1 = 0.;
 | 
						|
    for (i = 0; i < size; i++) {
 | 
						|
	w0 += we[i];
 | 
						|
	if (expand[i] == 0)
 | 
						|
	    w1 += we[i];
 | 
						|
    }
 | 
						|
    if (w0 <= 0.)
 | 
						|
	w0 = 1.;
 | 
						|
 | 
						|
    for (k = 0; k < cell->necell; k++) {
 | 
						|
	j = cell->eindex[k];
 | 
						|
	bcol = cell->col[j];
 | 
						|
	width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
 | 
						|
	w = weight(width);
 | 
						|
	s = w / (w1 + w);
 | 
						|
	b = sigma_td_nw((int)(s * maxwidth));
 | 
						|
	correct_table_matrix4(t, bcol, cell->colspan[j], expand, s, b);
 | 
						|
    }
 | 
						|
 | 
						|
    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 */
 | 
						|
 | 
						|
/* Local Variables:    */
 | 
						|
/* c-basic-offset: 4   */
 | 
						|
/* tab-width: 8        */
 | 
						|
/* End:                */
 |