~ubuntu-branches/debian/sid/w3m/sid

« back to all changes in this revision

Viewing changes to .pc/020_button.patch/table.c

  • Committer: Package Import Robot
  • Author(s): Tatsuya Kinoshita
  • Date: 2015-04-25 19:33:35 UTC
  • Revision ID: package-import@ubuntu.com-20150425193335-g4o8qj59ltroolv1
Tags: 0.5.3-20
* Integrate Debian changes into 020_debian.patch (closes: #776112)
  (debian/patches/*.patch except 010_upstream.patch are merged)
  - Improve English manpages
    (closes: #771003, #766550, #403634, #380560, #345084, #285251, #268211)
  - Fix Perl warnings (closes: #771004)
  - Update to 2015-02-03
* Add libsixel-bin to Suggests for img2sixel
* Set extbrowser to sensible-browser in w3mconfig
* Set mailer to use xdg-open in w3mconfig
* Add xdg-utils to Suggests for xdg-open
* Support committer date for gitlog2changelog
* Add dot to end of message for gitlog2changelog
* Update Vcs-Browser
* Update debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: table.c,v 1.58 2010/08/09 11:59:19 htrb Exp $ */
2
 
/* 
3
 
 * HTML table
4
 
 */
5
 
#include <sys/types.h>
6
 
#include <stdio.h>
7
 
#include <string.h>
8
 
#include <math.h>
9
 
#include "fm.h"
10
 
#include "html.h"
11
 
#include "parsetagx.h"
12
 
#include "Str.h"
13
 
#include "myctype.h"
14
 
 
15
 
int symbol_width = 0;
16
 
int symbol_width0 = 0;
17
 
 
18
 
#define RULE_WIDTH symbol_width
19
 
#define RULE(mode,n) (((mode) == BORDER_THICK) ? ((n) + 16) : (n))
20
 
#define TK_VERTICALBAR(mode) RULE(mode,5)
21
 
 
22
 
#define BORDERWIDTH     2
23
 
#define BORDERHEIGHT    1
24
 
#define NOBORDERWIDTH   1
25
 
#define NOBORDERHEIGHT  0
26
 
 
27
 
#define HTT_X   1
28
 
#define HTT_Y   2
29
 
#define HTT_ALIGN  0x30
30
 
#define HTT_LEFT   0x00
31
 
#define HTT_CENTER 0x10
32
 
#define HTT_RIGHT  0x20
33
 
#define HTT_TRSET  0x40
34
 
#define HTT_VALIGN 0x700
35
 
#define HTT_TOP    0x100
36
 
#define HTT_MIDDLE 0x200
37
 
#define HTT_BOTTOM 0x400
38
 
#define HTT_VTRSET 0x800
39
 
#ifdef NOWRAP
40
 
#define HTT_NOWRAP  4
41
 
#endif                          /* NOWRAP */
42
 
#define TAG_IS(s,tag,len) (strncasecmp(s,tag,len)==0&&(s[len] == '>' || IS_SPACE((int)s[len])))
43
 
 
44
 
#ifndef max
45
 
#define max(a,b)        ((a) > (b) ? (a) : (b))
46
 
#endif                          /* not max */
47
 
#ifndef min
48
 
#define min(a,b)        ((a) > (b) ? (b) : (a))
49
 
#endif                          /* not min */
50
 
#ifndef abs
51
 
#define abs(a)          ((a) >= 0. ? (a) : -(a))
52
 
#endif                          /* not abs */
53
 
 
54
 
#define set_prevchar(x,y,n) Strcopy_charp_n((x),(y),(n))
55
 
#define set_space_to_prevchar(x) Strcopy_charp_n((x)," ",1)
56
 
 
57
 
#ifdef MATRIX
58
 
#ifndef MESCHACH
59
 
#include "matrix.c"
60
 
#endif                          /* not MESCHACH */
61
 
#endif                          /* MATRIX */
62
 
 
63
 
#ifdef MATRIX
64
 
int correct_table_matrix(struct table *, int, int, int, double);
65
 
void set_table_matrix(struct table *, int);
66
 
#endif                          /* MATRIX */
67
 
 
68
 
#ifdef MATRIX
69
 
static double
70
 
weight(int x)
71
 
{
72
 
 
73
 
    if (x < COLS)
74
 
        return (double)x;
75
 
    else
76
 
        return COLS * (log((double)x / COLS) + 1.);
77
 
}
78
 
 
79
 
static double
80
 
weight2(int a)
81
 
{
82
 
    return (double)a / COLS * 4 + 1.;
83
 
}
84
 
 
85
 
#define sigma_td(a)       (0.5*weight2(a))      /* <td width=...> */
86
 
#define sigma_td_nw(a)    (32*weight2(a))       /* <td ...> */
87
 
#define sigma_table(a)    (0.25*weight2(a))     /* <table width=...> */
88
 
#define sigma_table_nw(a) (2*weight2(a))        /* <table...> */
89
 
#else                           /* not MATRIX */
90
 
#define LOG_MIN 1.0
91
 
static double
92
 
weight3(int x)
93
 
{
94
 
    if (x < 0.1)
95
 
        return 0.1;
96
 
    if (x < LOG_MIN)
97
 
        return (double)x;
98
 
    else
99
 
        return LOG_MIN * (log((double)x / LOG_MIN) + 1.);
100
 
}
101
 
#endif                          /* not MATRIX */
102
 
 
103
 
static int
104
 
bsearch_2short(short e1, short *ent1, short e2, short *ent2, int base,
105
 
               short *indexarray, int nent)
106
 
{
107
 
    int n = nent;
108
 
    int k = 0;
109
 
 
110
 
    int e = e1 * base + e2;
111
 
    while (n > 0) {
112
 
        int nn = n / 2;
113
 
        int idx = indexarray[k + nn];
114
 
        int ne = ent1[idx] * base + ent2[idx];
115
 
        if (ne == e) {
116
 
            k += nn;
117
 
            break;
118
 
        }
119
 
        else if (ne < e) {
120
 
            n -= nn + 1;
121
 
            k += nn + 1;
122
 
        }
123
 
        else {
124
 
            n = nn;
125
 
        }
126
 
    }
127
 
    return k;
128
 
}
129
 
 
130
 
static int
131
 
bsearch_double(double e, double *ent, short *indexarray, int nent)
132
 
{
133
 
    int n = nent;
134
 
    int k = 0;
135
 
 
136
 
    while (n > 0) {
137
 
        int nn = n / 2;
138
 
        int idx = indexarray[k + nn];
139
 
        double ne = ent[idx];
140
 
        if (ne == e) {
141
 
            k += nn;
142
 
            break;
143
 
        }
144
 
        else if (ne > e) {
145
 
            n -= nn + 1;
146
 
            k += nn + 1;
147
 
        }
148
 
        else {
149
 
            n = nn;
150
 
        }
151
 
    }
152
 
    return k;
153
 
}
154
 
 
155
 
static int
156
 
ceil_at_intervals(int x, int step)
157
 
{
158
 
    int mo = x % step;
159
 
    if (mo > 0)
160
 
        x += step - mo;
161
 
    else if (mo < 0)
162
 
        x -= mo;
163
 
    return x;
164
 
}
165
 
 
166
 
static int
167
 
floor_at_intervals(int x, int step)
168
 
{
169
 
    int mo = x % step;
170
 
    if (mo > 0)
171
 
        x -= mo;
172
 
    else if (mo < 0)
173
 
        x += step - mo;
174
 
    return x;
175
 
}
176
 
 
177
 
#define round(x) ((int)floor((x)+0.5))
178
 
 
179
 
#ifndef MATRIX
180
 
static void
181
 
dv2sv(double *dv, short *iv, int size)
182
 
{
183
 
    int i, k, iw;
184
 
    short *indexarray;
185
 
    double *edv;
186
 
    double w = 0., x;
187
 
 
188
 
    indexarray = NewAtom_N(short, size);
189
 
    edv = NewAtom_N(double, size);
190
 
    for (i = 0; i < size; i++) {
191
 
        iv[i] = ceil(dv[i]);
192
 
        edv[i] = (double)iv[i] - dv[i];
193
 
    }
194
 
 
195
 
    w = 0.;
196
 
    for (k = 0; k < size; k++) {
197
 
        x = edv[k];
198
 
        w += x;
199
 
        i = bsearch_double(x, edv, indexarray, k);
200
 
        if (k > i) {
201
 
            int ii;
202
 
            for (ii = k; ii > i; ii--)
203
 
                indexarray[ii] = indexarray[ii - 1];
204
 
        }
205
 
        indexarray[i] = k;
206
 
    }
207
 
    iw = min((int)(w + 0.5), size);
208
 
    if (iw == 0)
209
 
        return;
210
 
    x = edv[(int)indexarray[iw - 1]];
211
 
    for (i = 0; i < size; i++) {
212
 
        k = indexarray[i];
213
 
        if (i >= iw && abs(edv[k] - x) > 1e-6)
214
 
            break;
215
 
        iv[k]--;
216
 
    }
217
 
}
218
 
#endif
219
 
 
220
 
static int
221
 
table_colspan(struct table *t, int row, int col)
222
 
{
223
 
    int i;
224
 
    for (i = col + 1; i <= t->maxcol && (t->tabattr[row][i] & HTT_X); i++) ;
225
 
    return i - col;
226
 
}
227
 
 
228
 
static int
229
 
table_rowspan(struct table *t, int row, int col)
230
 
{
231
 
    int i;
232
 
    if (!t->tabattr[row])
233
 
        return 0;
234
 
    for (i = row + 1; i <= t->maxrow && t->tabattr[i] &&
235
 
         (t->tabattr[i][col] & HTT_Y); i++) ;
236
 
    return i - row;
237
 
}
238
 
 
239
 
static int
240
 
minimum_cellspacing(int border_mode)
241
 
{
242
 
    switch (border_mode) {
243
 
    case BORDER_THIN:
244
 
    case BORDER_THICK:
245
 
    case BORDER_NOWIN:
246
 
        return RULE_WIDTH;
247
 
    case BORDER_NONE:
248
 
        return 1;
249
 
    default:
250
 
        /* not reached */
251
 
        return 0;
252
 
    }
253
 
}
254
 
 
255
 
static int
256
 
table_border_width(struct table *t)
257
 
{
258
 
    switch (t->border_mode) {
259
 
    case BORDER_THIN:
260
 
    case BORDER_THICK:
261
 
        return t->maxcol * t->cellspacing + 2 * (RULE_WIDTH + t->cellpadding);
262
 
    case BORDER_NOWIN:
263
 
    case BORDER_NONE:
264
 
        return t->maxcol * t->cellspacing;
265
 
    default:
266
 
        /* not reached */
267
 
        return 0;
268
 
    }
269
 
}
270
 
 
271
 
struct table *
272
 
newTable()
273
 
{
274
 
    struct table *t;
275
 
    int i, j;
276
 
 
277
 
    t = New(struct table);
278
 
    t->max_rowsize = MAXROW;
279
 
    t->tabdata = New_N(GeneralList **, MAXROW);
280
 
    t->tabattr = New_N(table_attr *, MAXROW);
281
 
    t->tabheight = NewAtom_N(short, MAXROW);
282
 
#ifdef ID_EXT
283
 
    t->tabidvalue = New_N(Str *, MAXROW);
284
 
    t->tridvalue = New_N(Str, MAXROW);
285
 
#endif                          /* ID_EXT */
286
 
 
287
 
    for (i = 0; i < MAXROW; i++) {
288
 
        t->tabdata[i] = NULL;
289
 
        t->tabattr[i] = 0;
290
 
        t->tabheight[i] = 0;
291
 
#ifdef ID_EXT
292
 
        t->tabidvalue[i] = NULL;
293
 
        t->tridvalue[i] = NULL;
294
 
#endif                          /* ID_EXT */
295
 
    }
296
 
    for (j = 0; j < MAXCOL; j++) {
297
 
        t->tabwidth[j] = 0;
298
 
        t->minimum_width[j] = 0;
299
 
        t->fixed_width[j] = 0;
300
 
    }
301
 
    t->cell.maxcell = -1;
302
 
    t->cell.icell = -1;
303
 
    t->ntable = 0;
304
 
    t->tables_size = 0;
305
 
    t->tables = NULL;
306
 
#ifdef MATRIX
307
 
    t->matrix = NULL;
308
 
    t->vector = NULL;
309
 
#endif                          /* MATRIX */
310
 
#if 0
311
 
    t->tabcontentssize = 0;
312
 
    t->indent = 0;
313
 
    t->linfo.prev_ctype = PC_ASCII;
314
 
    t->linfo.prev_spaces = -1;
315
 
#endif
316
 
    t->linfo.prevchar = Strnew_size(8);
317
 
    set_prevchar(t->linfo.prevchar, "", 0);
318
 
    t->trattr = 0;
319
 
 
320
 
    t->caption = Strnew();
321
 
    t->suspended_data = NULL;
322
 
#ifdef ID_EXT
323
 
    t->id = NULL;
324
 
#endif
325
 
    return t;
326
 
}
327
 
 
328
 
static void
329
 
check_row(struct table *t, int row)
330
 
{
331
 
    int i, r;
332
 
    GeneralList ***tabdata;
333
 
    table_attr **tabattr;
334
 
    short *tabheight;
335
 
#ifdef ID_EXT
336
 
    Str **tabidvalue;
337
 
    Str *tridvalue;
338
 
#endif                          /* ID_EXT */
339
 
 
340
 
    if (row >= t->max_rowsize) {
341
 
        r = max(t->max_rowsize * 2, row + 1);
342
 
        tabdata = New_N(GeneralList **, r);
343
 
        tabattr = New_N(table_attr *, r);
344
 
        tabheight = NewAtom_N(short, r);
345
 
#ifdef ID_EXT
346
 
        tabidvalue = New_N(Str *, r);
347
 
        tridvalue = New_N(Str, r);
348
 
#endif                          /* ID_EXT */
349
 
        for (i = 0; i < t->max_rowsize; i++) {
350
 
            tabdata[i] = t->tabdata[i];
351
 
            tabattr[i] = t->tabattr[i];
352
 
            tabheight[i] = t->tabheight[i];
353
 
#ifdef ID_EXT
354
 
            tabidvalue[i] = t->tabidvalue[i];
355
 
            tridvalue[i] = t->tridvalue[i];
356
 
#endif                          /* ID_EXT */
357
 
        }
358
 
        for (; i < r; i++) {
359
 
            tabdata[i] = NULL;
360
 
            tabattr[i] = NULL;
361
 
            tabheight[i] = 0;
362
 
#ifdef ID_EXT
363
 
            tabidvalue[i] = NULL;
364
 
            tridvalue[i] = NULL;
365
 
#endif                          /* ID_EXT */
366
 
        }
367
 
        t->tabdata = tabdata;
368
 
        t->tabattr = tabattr;
369
 
        t->tabheight = tabheight;
370
 
#ifdef ID_EXT
371
 
        t->tabidvalue = tabidvalue;
372
 
        t->tridvalue = tridvalue;
373
 
#endif                          /* ID_EXT */
374
 
        t->max_rowsize = r;
375
 
    }
376
 
 
377
 
    if (t->tabdata[row] == NULL) {
378
 
        t->tabdata[row] = New_N(GeneralList *, MAXCOL);
379
 
        t->tabattr[row] = NewAtom_N(table_attr, MAXCOL);
380
 
#ifdef ID_EXT
381
 
        t->tabidvalue[row] = New_N(Str, MAXCOL);
382
 
#endif                          /* ID_EXT */
383
 
        for (i = 0; i < MAXCOL; i++) {
384
 
            t->tabdata[row][i] = NULL;
385
 
            t->tabattr[row][i] = 0;
386
 
#ifdef ID_EXT
387
 
            t->tabidvalue[row][i] = NULL;
388
 
#endif                          /* ID_EXT */
389
 
        }
390
 
    }
391
 
}
392
 
 
393
 
void
394
 
pushdata(struct table *t, int row, int col, char *data)
395
 
{
396
 
    check_row(t, row);
397
 
    if (t->tabdata[row][col] == NULL)
398
 
        t->tabdata[row][col] = newGeneralList();
399
 
 
400
 
    pushText(t->tabdata[row][col], data ? data : "");
401
 
}
402
 
 
403
 
void
404
 
suspend_or_pushdata(struct table *tbl, char *line)
405
 
{
406
 
    if (tbl->flag & TBL_IN_COL)
407
 
        pushdata(tbl, tbl->row, tbl->col, line);
408
 
    else {
409
 
        if (!tbl->suspended_data)
410
 
            tbl->suspended_data = newTextList();
411
 
        pushText(tbl->suspended_data, line ? line : "");
412
 
    }
413
 
}
414
 
 
415
 
#ifdef USE_M17N
416
 
#define PUSH_TAG(str,n) Strcat_charp_n(tagbuf, str, n)
417
 
#else
418
 
#define PUSH_TAG(str,n) Strcat_char(tagbuf, *str)
419
 
#endif
420
 
 
421
 
int visible_length_offset = 0;
422
 
int
423
 
visible_length(char *str)
424
 
{
425
 
    int len = 0, n, max_len = 0;
426
 
    int status = R_ST_NORMAL;
427
 
    int prev_status = status;
428
 
    Str tagbuf = Strnew();
429
 
    char *t, *r2;
430
 
    int amp_len = 0;
431
 
 
432
 
    t = str;
433
 
    while (*str) {
434
 
        prev_status = status;
435
 
        if (next_status(*str, &status)) {
436
 
#ifdef USE_M17N
437
 
            len += get_mcwidth(str);
438
 
            n = get_mclen(str);
439
 
        }
440
 
        else {
441
 
            n = 1;
442
 
        }
443
 
#else
444
 
            len++;
445
 
        }
446
 
#endif
447
 
        if (status == R_ST_TAG0) {
448
 
            Strclear(tagbuf);
449
 
            PUSH_TAG(str, n);
450
 
        }
451
 
        else if (status == R_ST_TAG || status == R_ST_DQUOTE
452
 
                 || status == R_ST_QUOTE || status == R_ST_EQL
453
 
                 || status == R_ST_VALUE) {
454
 
            PUSH_TAG(str, n);
455
 
        }
456
 
        else if (status == R_ST_AMP) {
457
 
            if (prev_status == R_ST_NORMAL) {
458
 
                Strclear(tagbuf);
459
 
                len--;
460
 
                amp_len = 0;
461
 
            }
462
 
            else {
463
 
                PUSH_TAG(str, n);
464
 
                amp_len++;
465
 
            }
466
 
        }
467
 
        else if (status == R_ST_NORMAL && prev_status == R_ST_AMP) {
468
 
            PUSH_TAG(str, n);
469
 
            r2 = tagbuf->ptr;
470
 
            t = getescapecmd(&r2);
471
 
            if (!*r2 && (*t == '\r' || *t == '\n')) {
472
 
                if (len > max_len)
473
 
                    max_len = len;
474
 
                len = 0;
475
 
            }
476
 
            else
477
 
                len += get_strwidth(t) + get_strwidth(r2);
478
 
        }
479
 
        else if (status == R_ST_NORMAL && ST_IS_REAL_TAG(prev_status)) {
480
 
            ;
481
 
        }
482
 
        else if (*str == '\t') {
483
 
            len--;
484
 
            do {
485
 
                len++;
486
 
            } while ((visible_length_offset + len) % Tabstop != 0);
487
 
        }
488
 
        else if (*str == '\r' || *str == '\n') {
489
 
            len--;
490
 
            if (len > max_len)
491
 
                max_len = len;
492
 
            len = 0;
493
 
        }
494
 
#ifdef USE_M17N
495
 
        str += n;
496
 
#else
497
 
        str++;
498
 
#endif
499
 
    }
500
 
    if (status == R_ST_AMP) {
501
 
        r2 = tagbuf->ptr;
502
 
        t = getescapecmd(&r2);
503
 
        if (*t != '\r' && *t != '\n')
504
 
            len += get_strwidth(t) + get_strwidth(r2);
505
 
    }
506
 
    return len > max_len ? len : max_len;
507
 
}
508
 
 
509
 
int
510
 
visible_length_plain(char *str)
511
 
{
512
 
    int len = 0, max_len = 0;
513
 
 
514
 
    while (*str) {
515
 
        if (*str == '\t') {
516
 
            do {
517
 
                len++;
518
 
            } while ((visible_length_offset + len) % Tabstop != 0);
519
 
            str++;
520
 
        }
521
 
        else if (*str == '\r' || *str == '\n') {
522
 
            if (len > max_len)
523
 
                max_len = len;
524
 
            len = 0;
525
 
            str++;
526
 
        }
527
 
        else {
528
 
#ifdef USE_M17N
529
 
            len += get_mcwidth(str);
530
 
            str += get_mclen(str);
531
 
#else
532
 
            len++;
533
 
            str++;
534
 
#endif
535
 
        }
536
 
    }
537
 
    return len > max_len ? len : max_len;
538
 
}
539
 
 
540
 
static int
541
 
maximum_visible_length(char *str, int offset)
542
 
{
543
 
    visible_length_offset = offset;
544
 
    return visible_length(str);
545
 
}
546
 
 
547
 
static int
548
 
maximum_visible_length_plain(char *str, int offset)
549
 
{
550
 
    visible_length_offset = offset;
551
 
    return visible_length_plain(str);
552
 
}
553
 
 
554
 
void
555
 
align(TextLine *lbuf, int width, int mode)
556
 
{
557
 
    int i, l, l1, l2;
558
 
    Str buf, line = lbuf->line;
559
 
 
560
 
    if (line->length == 0) {
561
 
        for (i = 0; i < width; i++)
562
 
            Strcat_char(line, ' ');
563
 
        lbuf->pos = width;
564
 
        return;
565
 
    }
566
 
    buf = Strnew();
567
 
    l = width - lbuf->pos;
568
 
    switch (mode) {
569
 
    case ALIGN_CENTER:
570
 
        l1 = l / 2;
571
 
        l2 = l - l1;
572
 
        for (i = 0; i < l1; i++)
573
 
            Strcat_char(buf, ' ');
574
 
        Strcat(buf, line);
575
 
        for (i = 0; i < l2; i++)
576
 
            Strcat_char(buf, ' ');
577
 
        break;
578
 
    case ALIGN_LEFT:
579
 
        Strcat(buf, line);
580
 
        for (i = 0; i < l; i++)
581
 
            Strcat_char(buf, ' ');
582
 
        break;
583
 
    case ALIGN_RIGHT:
584
 
        for (i = 0; i < l; i++)
585
 
            Strcat_char(buf, ' ');
586
 
        Strcat(buf, line);
587
 
        break;
588
 
    default:
589
 
        return;
590
 
    }
591
 
    lbuf->line = buf;
592
 
    if (lbuf->pos < width)
593
 
        lbuf->pos = width;
594
 
}
595
 
 
596
 
void
597
 
print_item(struct table *t, int row, int col, int width, Str buf)
598
 
{
599
 
    int alignment;
600
 
    TextLine *lbuf;
601
 
 
602
 
    if (t->tabdata[row])
603
 
        lbuf = popTextLine(t->tabdata[row][col]);
604
 
    else
605
 
        lbuf = NULL;
606
 
 
607
 
    if (lbuf != NULL) {
608
 
        check_row(t, row);
609
 
        alignment = ALIGN_CENTER;
610
 
        if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_LEFT)
611
 
            alignment = ALIGN_LEFT;
612
 
        else if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_RIGHT)
613
 
            alignment = ALIGN_RIGHT;
614
 
        else if ((t->tabattr[row][col] & HTT_ALIGN) == HTT_CENTER)
615
 
            alignment = ALIGN_CENTER;
616
 
        align(lbuf, width, alignment);
617
 
        Strcat(buf, lbuf->line);
618
 
    }
619
 
    else {
620
 
        lbuf = newTextLine(NULL, 0);
621
 
        align(lbuf, width, ALIGN_CENTER);
622
 
        Strcat(buf, lbuf->line);
623
 
    }
624
 
}
625
 
 
626
 
 
627
 
#define T_TOP           0
628
 
#define T_MIDDLE        1
629
 
#define T_BOTTOM        2
630
 
 
631
 
void
632
 
print_sep(struct table *t, int row, int type, int maxcol, Str buf)
633
 
{
634
 
    int forbid;
635
 
    int rule_mode;
636
 
    int i, k, l, m;
637
 
 
638
 
    if (row >= 0)
639
 
        check_row(t, row);
640
 
    check_row(t, row + 1);
641
 
    if ((type == T_TOP || type == T_BOTTOM) && t->border_mode == BORDER_THICK) {
642
 
        rule_mode = BORDER_THICK;
643
 
    }
644
 
    else {
645
 
        rule_mode = BORDER_THIN;
646
 
    }
647
 
    forbid = 1;
648
 
    if (type == T_TOP)
649
 
        forbid |= 2;
650
 
    else if (type == T_BOTTOM)
651
 
        forbid |= 8;
652
 
    else if (t->tabattr[row + 1][0] & HTT_Y) {
653
 
        forbid |= 4;
654
 
    }
655
 
    if (t->border_mode != BORDER_NOWIN) {
656
 
        push_symbol(buf, RULE(t->border_mode, forbid), symbol_width, 1);
657
 
    }
658
 
    for (i = 0; i <= maxcol; i++) {
659
 
        forbid = 10;
660
 
        if (type != T_BOTTOM && (t->tabattr[row + 1][i] & HTT_Y)) {
661
 
            if (t->tabattr[row + 1][i] & HTT_X) {
662
 
                goto do_last_sep;
663
 
            }
664
 
            else {
665
 
                for (k = row;
666
 
                     k >= 0 && t->tabattr[k] && (t->tabattr[k][i] & HTT_Y);
667
 
                     k--) ;
668
 
                m = t->tabwidth[i] + 2 * t->cellpadding;
669
 
                for (l = i + 1; l <= t->maxcol && (t->tabattr[row][l] & HTT_X);
670
 
                     l++)
671
 
                    m += t->tabwidth[l] + t->cellspacing;
672
 
                print_item(t, k, i, m, buf);
673
 
            }
674
 
        }
675
 
        else {
676
 
            int w = t->tabwidth[i] + 2 * t->cellpadding;
677
 
            if (RULE_WIDTH == 2)
678
 
                w = (w + 1) / RULE_WIDTH;
679
 
            push_symbol(buf, RULE(rule_mode, forbid), symbol_width, w);
680
 
        }
681
 
      do_last_sep:
682
 
        if (i < maxcol) {
683
 
            forbid = 0;
684
 
            if (type == T_TOP)
685
 
                forbid |= 2;
686
 
            else if (t->tabattr[row][i + 1] & HTT_X) {
687
 
                forbid |= 2;
688
 
            }
689
 
            if (type == T_BOTTOM)
690
 
                forbid |= 8;
691
 
            else {
692
 
                if (t->tabattr[row + 1][i + 1] & HTT_X) {
693
 
                    forbid |= 8;
694
 
                }
695
 
                if (t->tabattr[row + 1][i + 1] & HTT_Y) {
696
 
                    forbid |= 4;
697
 
                }
698
 
                if (t->tabattr[row + 1][i] & HTT_Y) {
699
 
                    forbid |= 1;
700
 
                }
701
 
            }
702
 
            if (forbid != 15)   /* forbid==15 means 'no rule at all' */
703
 
                push_symbol(buf, RULE(rule_mode, forbid), symbol_width, 1);
704
 
        }
705
 
    }
706
 
    forbid = 4;
707
 
    if (type == T_TOP)
708
 
        forbid |= 2;
709
 
    if (type == T_BOTTOM)
710
 
        forbid |= 8;
711
 
    if (t->tabattr[row + 1][maxcol] & HTT_Y) {
712
 
        forbid |= 1;
713
 
    }
714
 
    if (t->border_mode != BORDER_NOWIN)
715
 
        push_symbol(buf, RULE(t->border_mode, forbid), symbol_width, 1);
716
 
}
717
 
 
718
 
static int
719
 
get_spec_cell_width(struct table *tbl, int row, int col)
720
 
{
721
 
    int i, w;
722
 
 
723
 
    w = tbl->tabwidth[col];
724
 
    for (i = col + 1; i <= tbl->maxcol; i++) {
725
 
        check_row(tbl, row);
726
 
        if (tbl->tabattr[row][i] & HTT_X)
727
 
            w += tbl->tabwidth[i] + tbl->cellspacing;
728
 
        else
729
 
            break;
730
 
    }
731
 
    return w;
732
 
}
733
 
 
734
 
void
735
 
do_refill(struct table *tbl, int row, int col, int maxlimit)
736
 
{
737
 
    TextList *orgdata;
738
 
    TextListItem *l;
739
 
    struct readbuffer obuf;
740
 
    struct html_feed_environ h_env;
741
 
    struct environment envs[MAX_ENV_LEVEL];
742
 
    int colspan, icell;
743
 
 
744
 
    if (tbl->tabdata[row] == NULL || tbl->tabdata[row][col] == NULL)
745
 
        return;
746
 
    orgdata = (TextList *)tbl->tabdata[row][col];
747
 
    tbl->tabdata[row][col] = newGeneralList();
748
 
 
749
 
    init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL,
750
 
              (TextLineList *)tbl->tabdata[row][col],
751
 
              get_spec_cell_width(tbl, row, col), 0);
752
 
    obuf.flag |= RB_INTABLE;
753
 
    if (h_env.limit > maxlimit)
754
 
        h_env.limit = maxlimit;
755
 
    if (tbl->border_mode != BORDER_NONE && tbl->vcellpadding > 0)
756
 
        do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
757
 
    for (l = orgdata->first; l != NULL; l = l->next) {
758
 
        if (TAG_IS(l->ptr, "<table_alt", 10)) {
759
 
            int id = -1;
760
 
            char *p = l->ptr;
761
 
            struct parsed_tag *tag;
762
 
            if ((tag = parse_tag(&p, TRUE)) != NULL)
763
 
                parsedtag_get_value(tag, ATTR_TID, &id);
764
 
            if (id >= 0 && id < tbl->ntable) {
765
 
                int alignment;
766
 
                TextLineListItem *ti;
767
 
                struct table *t = tbl->tables[id].ptr;
768
 
                int limit = tbl->tables[id].indent + t->total_width;
769
 
                tbl->tables[id].ptr = NULL;
770
 
                save_fonteffect(&h_env, h_env.obuf);
771
 
                flushline(&h_env, &obuf, 0, 2, h_env.limit);
772
 
                if (t->vspace > 0 && !(obuf.flag & RB_IGNORE_P))
773
 
                    do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
774
 
                if (RB_GET_ALIGN(h_env.obuf) == RB_CENTER)
775
 
                    alignment = ALIGN_CENTER;
776
 
                else if (RB_GET_ALIGN(h_env.obuf) == RB_RIGHT)
777
 
                    alignment = ALIGN_RIGHT;
778
 
                else
779
 
                    alignment = ALIGN_LEFT;
780
 
 
781
 
                if (alignment != ALIGN_LEFT) {
782
 
                    for (ti = tbl->tables[id].buf->first;
783
 
                         ti != NULL; ti = ti->next)
784
 
                        align(ti->ptr, h_env.limit, alignment);
785
 
                }
786
 
                appendTextLineList(h_env.buf, tbl->tables[id].buf);
787
 
                if (h_env.maxlimit < limit)
788
 
                    h_env.maxlimit = limit;
789
 
                restore_fonteffect(&h_env, h_env.obuf);
790
 
                obuf.flag &= ~RB_IGNORE_P;
791
 
                h_env.blank_lines = 0;
792
 
                if (t->vspace > 0) {
793
 
                    do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
794
 
                    obuf.flag |= RB_IGNORE_P;
795
 
                }
796
 
            }
797
 
        }
798
 
        else
799
 
            HTMLlineproc1(l->ptr, &h_env);
800
 
    }
801
 
    if (obuf.status != R_ST_NORMAL) {
802
 
        obuf.status = R_ST_EOL;
803
 
        HTMLlineproc1("\n", &h_env);
804
 
    }
805
 
    completeHTMLstream(&h_env, &obuf);
806
 
    flushline(&h_env, &obuf, 0, 2, h_env.limit);
807
 
    if (tbl->border_mode == BORDER_NONE) {
808
 
        int rowspan = table_rowspan(tbl, row, col);
809
 
        if (row + rowspan <= tbl->maxrow) {
810
 
            if (tbl->vcellpadding > 0 && !(obuf.flag & RB_IGNORE_P))
811
 
                do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
812
 
        }
813
 
        else {
814
 
            if (tbl->vspace > 0)
815
 
                purgeline(&h_env);
816
 
        }
817
 
    }
818
 
    else {
819
 
        if (tbl->vcellpadding > 0) {
820
 
            if (!(obuf.flag & RB_IGNORE_P))
821
 
                do_blankline(&h_env, &obuf, 0, 0, h_env.limit);
822
 
        }
823
 
        else
824
 
            purgeline(&h_env);
825
 
    }
826
 
    if ((colspan = table_colspan(tbl, row, col)) > 1) {
827
 
        struct table_cell *cell = &tbl->cell;
828
 
        int k;
829
 
        k = bsearch_2short(colspan, cell->colspan, col, cell->col, MAXCOL,
830
 
                           cell->index, cell->maxcell + 1);
831
 
        icell = cell->index[k];
832
 
        if (cell->minimum_width[icell] < h_env.maxlimit)
833
 
            cell->minimum_width[icell] = h_env.maxlimit;
834
 
    }
835
 
    else {
836
 
        if (tbl->minimum_width[col] < h_env.maxlimit)
837
 
            tbl->minimum_width[col] = h_env.maxlimit;
838
 
    }
839
 
}
840
 
 
841
 
static int
842
 
table_rule_width(struct table *t)
843
 
{
844
 
    if (t->border_mode == BORDER_NONE)
845
 
        return 1;
846
 
    return RULE_WIDTH;
847
 
}
848
 
 
849
 
static void
850
 
check_cell_width(short *tabwidth, short *cellwidth,
851
 
                 short *col, short *colspan, short maxcell,
852
 
                 short *indexarray, int space, int dir)
853
 
{
854
 
    int i, j, k, bcol, ecol;
855
 
    int swidth, width;
856
 
 
857
 
    for (k = 0; k <= maxcell; k++) {
858
 
        j = indexarray[k];
859
 
        if (cellwidth[j] <= 0)
860
 
            continue;
861
 
        bcol = col[j];
862
 
        ecol = bcol + colspan[j];
863
 
        swidth = 0;
864
 
        for (i = bcol; i < ecol; i++)
865
 
            swidth += tabwidth[i];
866
 
 
867
 
        width = cellwidth[j] - (colspan[j] - 1) * space;
868
 
        if (width > swidth) {
869
 
            int w = (width - swidth) / colspan[j];
870
 
            int r = (width - swidth) % colspan[j];
871
 
            for (i = bcol; i < ecol; i++)
872
 
                tabwidth[i] += w;
873
 
            /* dir {0: horizontal, 1: vertical} */
874
 
            if (dir == 1 && r > 0)
875
 
                r = colspan[j];
876
 
            for (i = 1; i <= r; i++)
877
 
                tabwidth[ecol - i]++;
878
 
        }
879
 
    }
880
 
}
881
 
 
882
 
void
883
 
check_minimum_width(struct table *t, short *tabwidth)
884
 
{
885
 
    int i;
886
 
    struct table_cell *cell = &t->cell;
887
 
 
888
 
    for (i = 0; i <= t->maxcol; i++) {
889
 
        if (tabwidth[i] < t->minimum_width[i])
890
 
            tabwidth[i] = t->minimum_width[i];
891
 
    }
892
 
 
893
 
    check_cell_width(tabwidth, cell->minimum_width, cell->col, cell->colspan,
894
 
                     cell->maxcell, cell->index, t->cellspacing, 0);
895
 
}
896
 
 
897
 
void
898
 
check_maximum_width(struct table *t)
899
 
{
900
 
    struct table_cell *cell = &t->cell;
901
 
#ifdef MATRIX
902
 
    int i, j, bcol, ecol;
903
 
    int swidth, width;
904
 
 
905
 
    cell->necell = 0;
906
 
    for (j = 0; j <= cell->maxcell; j++) {
907
 
        bcol = cell->col[j];
908
 
        ecol = bcol + cell->colspan[j];
909
 
        swidth = 0;
910
 
        for (i = bcol; i < ecol; i++)
911
 
            swidth += t->tabwidth[i];
912
 
 
913
 
        width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
914
 
        if (width > swidth) {
915
 
            cell->eindex[cell->necell] = j;
916
 
            cell->necell++;
917
 
        }
918
 
    }
919
 
#else                           /* not MATRIX */
920
 
    check_cell_width(t->tabwidth, cell->width, cell->col, cell->colspan,
921
 
                     cell->maxcell, cell->index, t->cellspacing, 0);
922
 
    check_minimum_width(t, t->tabwidth);
923
 
#endif                          /* not MATRIX */
924
 
}
925
 
 
926
 
 
927
 
#ifdef MATRIX
928
 
static void
929
 
set_integered_width(struct table *t, double *dwidth, short *iwidth)
930
 
{
931
 
    int i, j, k, n, bcol, ecol, step;
932
 
    short *indexarray;
933
 
    char *fixed;
934
 
    double *mod;
935
 
    double sum = 0., x = 0.;
936
 
    struct table_cell *cell = &t->cell;
937
 
    int rulewidth = table_rule_width(t);
938
 
 
939
 
    indexarray = NewAtom_N(short, t->maxcol + 1);
940
 
    mod = NewAtom_N(double, t->maxcol + 1);
941
 
    for (i = 0; i <= t->maxcol; i++) {
942
 
        iwidth[i] = ceil_at_intervals(ceil(dwidth[i]), rulewidth);
943
 
        mod[i] = (double)iwidth[i] - dwidth[i];
944
 
    }
945
 
 
946
 
    sum = 0.;
947
 
    for (k = 0; k <= t->maxcol; k++) {
948
 
        x = mod[k];
949
 
        sum += x;
950
 
        i = bsearch_double(x, mod, indexarray, k);
951
 
        if (k > i) {
952
 
            int ii;
953
 
            for (ii = k; ii > i; ii--)
954
 
                indexarray[ii] = indexarray[ii - 1];
955
 
        }
956
 
        indexarray[i] = k;
957
 
    }
958
 
 
959
 
    fixed = NewAtom_N(char, t->maxcol + 1);
960
 
    bzero(fixed, t->maxcol + 1);
961
 
    for (step = 0; step < 2; step++) {
962
 
        for (i = 0; i <= t->maxcol; i += n) {
963
 
            int nn;
964
 
            char *idx;
965
 
            double nsum;
966
 
            if (sum < 0.5)
967
 
                return;
968
 
            for (n = 0; i + n <= t->maxcol; n++) {
969
 
                int ii = indexarray[i + n];
970
 
                if (n == 0)
971
 
                    x = mod[ii];
972
 
                else if (fabs(mod[ii] - x) > 1e-6)
973
 
                    break;
974
 
            }
975
 
            for (k = 0; k < n; k++) {
976
 
                int ii = indexarray[i + k];
977
 
                if (fixed[ii] < 2 &&
978
 
                    iwidth[ii] - rulewidth < t->minimum_width[ii])
979
 
                    fixed[ii] = 2;
980
 
                if (fixed[ii] < 1 &&
981
 
                    iwidth[ii] - rulewidth < t->tabwidth[ii] &&
982
 
                    (double)rulewidth - mod[ii] > 0.5)
983
 
                    fixed[ii] = 1;
984
 
            }
985
 
            idx = NewAtom_N(char, n);
986
 
            for (k = 0; k < cell->maxcell; k++) {
987
 
                int kk, w, width, m;
988
 
                j = cell->index[k];
989
 
                bcol = cell->col[j];
990
 
                ecol = bcol + cell->colspan[j];
991
 
                m = 0;
992
 
                for (kk = 0; kk < n; kk++) {
993
 
                    int ii = indexarray[i + kk];
994
 
                    if (ii >= bcol && ii < ecol) {
995
 
                        idx[m] = ii;
996
 
                        m++;
997
 
                    }
998
 
                }
999
 
                if (m == 0)
1000
 
                    continue;
1001
 
                width = (cell->colspan[j] - 1) * t->cellspacing;
1002
 
                for (kk = bcol; kk < ecol; kk++)
1003
 
                    width += iwidth[kk];
1004
 
                w = 0;
1005
 
                for (kk = 0; kk < m; kk++) {
1006
 
                    if (fixed[(int)idx[kk]] < 2)
1007
 
                        w += rulewidth;
1008
 
                }
1009
 
                if (width - w < cell->minimum_width[j]) {
1010
 
                    for (kk = 0; kk < m; kk++) {
1011
 
                        if (fixed[(int)idx[kk]] < 2)
1012
 
                            fixed[(int)idx[kk]] = 2;
1013
 
                    }
1014
 
                }
1015
 
                w = 0;
1016
 
                for (kk = 0; kk < m; kk++) {
1017
 
                    if (fixed[(int)idx[kk]] < 1 &&
1018
 
                        (double)rulewidth - mod[(int)idx[kk]] > 0.5)
1019
 
                        w += rulewidth;
1020
 
                }
1021
 
                if (width - w < cell->width[j]) {
1022
 
                    for (kk = 0; kk < m; kk++) {
1023
 
                        if (fixed[(int)idx[kk]] < 1 &&
1024
 
                            (double)rulewidth - mod[(int)idx[kk]] > 0.5)
1025
 
                            fixed[(int)idx[kk]] = 1;
1026
 
                    }
1027
 
                }
1028
 
            }
1029
 
            nn = 0;
1030
 
            for (k = 0; k < n; k++) {
1031
 
                int ii = indexarray[i + k];
1032
 
                if (fixed[ii] <= step)
1033
 
                    nn++;
1034
 
            }
1035
 
            nsum = sum - (double)(nn * rulewidth);
1036
 
            if (nsum < 0. && fabs(sum) <= fabs(nsum))
1037
 
                return;
1038
 
            for (k = 0; k < n; k++) {
1039
 
                int ii = indexarray[i + k];
1040
 
                if (fixed[ii] <= step) {
1041
 
                    iwidth[ii] -= rulewidth;
1042
 
                    fixed[ii] = 3;
1043
 
                }
1044
 
            }
1045
 
            sum = nsum;
1046
 
        }
1047
 
    }
1048
 
}
1049
 
 
1050
 
static double
1051
 
correlation_coefficient(double sxx, double syy, double sxy)
1052
 
{
1053
 
    double coe, tmp;
1054
 
    tmp = sxx * syy;
1055
 
    if (tmp < Tiny)
1056
 
        tmp = Tiny;
1057
 
    coe = sxy / sqrt(tmp);
1058
 
    if (coe > 1.)
1059
 
        return 1.;
1060
 
    if (coe < -1.)
1061
 
        return -1.;
1062
 
    return coe;
1063
 
}
1064
 
 
1065
 
static double
1066
 
correlation_coefficient2(double sxx, double syy, double sxy)
1067
 
{
1068
 
    double coe, tmp;
1069
 
    tmp = (syy + sxx - 2 * sxy) * sxx;
1070
 
    if (tmp < Tiny)
1071
 
        tmp = Tiny;
1072
 
    coe = (sxx - sxy) / sqrt(tmp);
1073
 
    if (coe > 1.)
1074
 
        return 1.;
1075
 
    if (coe < -1.)
1076
 
        return -1.;
1077
 
    return coe;
1078
 
}
1079
 
 
1080
 
static double
1081
 
recalc_width(double old, double swidth, int cwidth,
1082
 
             double sxx, double syy, double sxy, int is_inclusive)
1083
 
{
1084
 
    double delta = swidth - (double)cwidth;
1085
 
    double rat = sxy / sxx,
1086
 
        coe = correlation_coefficient(sxx, syy, sxy), w, ww;
1087
 
    if (old < 0.)
1088
 
        old = 0.;
1089
 
    if (fabs(coe) < 1e-5)
1090
 
        return old;
1091
 
    w = rat * old;
1092
 
    ww = delta;
1093
 
    if (w > 0.) {
1094
 
        double wmin = 5e-3 * sqrt(syy * (1. - coe * coe));
1095
 
        if (swidth < 0.2 && cwidth > 0 && is_inclusive) {
1096
 
            double coe1 = correlation_coefficient2(sxx, syy, sxy);
1097
 
            if (coe > 0.9 || coe1 > 0.9)
1098
 
                return 0.;
1099
 
        }
1100
 
        if (wmin > 0.05)
1101
 
            wmin = 0.05;
1102
 
        if (ww < 0.)
1103
 
            ww = 0.;
1104
 
        ww += wmin;
1105
 
    }
1106
 
    else {
1107
 
        double wmin = 5e-3 * sqrt(syy) * fabs(coe);
1108
 
        if (rat > -0.001)
1109
 
            return old;
1110
 
        if (wmin > 0.01)
1111
 
            wmin = 0.01;
1112
 
        if (ww > 0.)
1113
 
            ww = 0.;
1114
 
        ww -= wmin;
1115
 
    }
1116
 
    if (w > ww)
1117
 
        return ww / rat;
1118
 
    return old;
1119
 
}
1120
 
 
1121
 
static int
1122
 
check_compressible_cell(struct table *t, MAT * minv,
1123
 
                        double *newwidth, double *swidth, short *cwidth,
1124
 
                        double totalwidth, double *Sxx,
1125
 
                        int icol, int icell, double sxx, int corr)
1126
 
{
1127
 
    struct table_cell *cell = &t->cell;
1128
 
    int i, j, k, m, bcol, ecol, span;
1129
 
    double delta, owidth;
1130
 
    double dmax, dmin, sxy;
1131
 
    int rulewidth = table_rule_width(t);
1132
 
 
1133
 
    if (sxx < 10.)
1134
 
        return corr;
1135
 
 
1136
 
    if (icol >= 0) {
1137
 
        owidth = newwidth[icol];
1138
 
        delta = newwidth[icol] - (double)t->tabwidth[icol];
1139
 
        bcol = icol;
1140
 
        ecol = bcol + 1;
1141
 
    }
1142
 
    else if (icell >= 0) {
1143
 
        owidth = swidth[icell];
1144
 
        delta = swidth[icell] - (double)cwidth[icell];
1145
 
        bcol = cell->col[icell];
1146
 
        ecol = bcol + cell->colspan[icell];
1147
 
    }
1148
 
    else {
1149
 
        owidth = totalwidth;
1150
 
        delta = totalwidth;
1151
 
        bcol = 0;
1152
 
        ecol = t->maxcol + 1;
1153
 
    }
1154
 
 
1155
 
    dmin = delta;
1156
 
    dmax = -1.;
1157
 
    for (k = 0; k <= cell->maxcell; k++) {
1158
 
        int bcol1, ecol1;
1159
 
        int is_inclusive = 0;
1160
 
        if (dmin <= 0.)
1161
 
            goto _end;
1162
 
        j = cell->index[k];
1163
 
        if (j == icell)
1164
 
            continue;
1165
 
        bcol1 = cell->col[j];
1166
 
        ecol1 = bcol1 + cell->colspan[j];
1167
 
        sxy = 0.;
1168
 
        for (m = bcol1; m < ecol1; m++) {
1169
 
            for (i = bcol; i < ecol; i++)
1170
 
                sxy += m_entry(minv, i, m);
1171
 
        }
1172
 
        if (bcol1 >= bcol && ecol1 <= ecol) {
1173
 
            is_inclusive = 1;
1174
 
        }
1175
 
        if (sxy > 0.)
1176
 
            dmin = recalc_width(dmin, swidth[j], cwidth[j],
1177
 
                                sxx, Sxx[j], sxy, is_inclusive);
1178
 
        else
1179
 
            dmax = recalc_width(dmax, swidth[j], cwidth[j],
1180
 
                                sxx, Sxx[j], sxy, is_inclusive);
1181
 
    }
1182
 
    for (m = 0; m <= t->maxcol; m++) {
1183
 
        int is_inclusive = 0;
1184
 
        if (dmin <= 0.)
1185
 
            goto _end;
1186
 
        if (m == icol)
1187
 
            continue;
1188
 
        sxy = 0.;
1189
 
        for (i = bcol; i < ecol; i++)
1190
 
            sxy += m_entry(minv, i, m);
1191
 
        if (m >= bcol && m < ecol) {
1192
 
            is_inclusive = 1;
1193
 
        }
1194
 
        if (sxy > 0.)
1195
 
            dmin = recalc_width(dmin, newwidth[m], t->tabwidth[m],
1196
 
                                sxx, m_entry(minv, m, m), sxy, is_inclusive);
1197
 
        else
1198
 
            dmax = recalc_width(dmax, newwidth[m], t->tabwidth[m],
1199
 
                                sxx, m_entry(minv, m, m), sxy, is_inclusive);
1200
 
    }
1201
 
  _end:
1202
 
    if (dmax > 0. && dmin > dmax)
1203
 
        dmin = dmax;
1204
 
    span = ecol - bcol;
1205
 
    if ((span == t->maxcol + 1 && dmin >= 0.) ||
1206
 
        (span != t->maxcol + 1 && dmin > rulewidth * 0.5)) {
1207
 
        int nwidth = ceil_at_intervals(round(owidth - dmin), rulewidth);
1208
 
        correct_table_matrix(t, bcol, ecol - bcol, nwidth, 1.);
1209
 
        corr++;
1210
 
    }
1211
 
    return corr;
1212
 
}
1213
 
 
1214
 
#define MAX_ITERATION 10
1215
 
int
1216
 
check_table_width(struct table *t, double *newwidth, MAT * minv, int itr)
1217
 
{
1218
 
    int i, j, k, m, bcol, ecol;
1219
 
    int corr = 0;
1220
 
    struct table_cell *cell = &t->cell;
1221
 
#ifdef __GNUC__
1222
 
    short orgwidth[t->maxcol + 1], corwidth[t->maxcol + 1];
1223
 
    short cwidth[cell->maxcell + 1];
1224
 
    double swidth[cell->maxcell + 1];
1225
 
#else                           /* __GNUC__ */
1226
 
    short orgwidth[MAXCOL], corwidth[MAXCOL];
1227
 
    short cwidth[MAXCELL];
1228
 
    double swidth[MAXCELL];
1229
 
#endif                          /* __GNUC__ */
1230
 
    double twidth, sxy, *Sxx, stotal;
1231
 
 
1232
 
    twidth = 0.;
1233
 
    stotal = 0.;
1234
 
    for (i = 0; i <= t->maxcol; i++) {
1235
 
        twidth += newwidth[i];
1236
 
        stotal += m_entry(minv, i, i);
1237
 
        for (m = 0; m < i; m++) {
1238
 
            stotal += 2 * m_entry(minv, i, m);
1239
 
        }
1240
 
    }
1241
 
 
1242
 
    Sxx = NewAtom_N(double, cell->maxcell + 1);
1243
 
    for (k = 0; k <= cell->maxcell; k++) {
1244
 
        j = cell->index[k];
1245
 
        bcol = cell->col[j];
1246
 
        ecol = bcol + cell->colspan[j];
1247
 
        swidth[j] = 0.;
1248
 
        for (i = bcol; i < ecol; i++)
1249
 
            swidth[j] += newwidth[i];
1250
 
        cwidth[j] = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
1251
 
        Sxx[j] = 0.;
1252
 
        for (i = bcol; i < ecol; i++) {
1253
 
            Sxx[j] += m_entry(minv, i, i);
1254
 
            for (m = bcol; m <= ecol; m++) {
1255
 
                if (m < i)
1256
 
                    Sxx[j] += 2 * m_entry(minv, i, m);
1257
 
            }
1258
 
        }
1259
 
    }
1260
 
 
1261
 
    /* compress table */
1262
 
    corr = check_compressible_cell(t, minv, newwidth, swidth,
1263
 
                                   cwidth, twidth, Sxx, -1, -1, stotal, corr);
1264
 
    if (itr < MAX_ITERATION && corr > 0)
1265
 
        return corr;
1266
 
 
1267
 
    /* compress multicolumn cell */
1268
 
    for (k = cell->maxcell; k >= 0; k--) {
1269
 
        j = cell->index[k];
1270
 
        corr = check_compressible_cell(t, minv, newwidth, swidth,
1271
 
                                       cwidth, twidth, Sxx,
1272
 
                                       -1, j, Sxx[j], corr);
1273
 
        if (itr < MAX_ITERATION && corr > 0)
1274
 
            return corr;
1275
 
    }
1276
 
 
1277
 
    /* compress single column cell */
1278
 
    for (i = 0; i <= t->maxcol; i++) {
1279
 
        corr = check_compressible_cell(t, minv, newwidth, swidth,
1280
 
                                       cwidth, twidth, Sxx,
1281
 
                                       i, -1, m_entry(minv, i, i), corr);
1282
 
        if (itr < MAX_ITERATION && corr > 0)
1283
 
            return corr;
1284
 
    }
1285
 
 
1286
 
 
1287
 
    for (i = 0; i <= t->maxcol; i++)
1288
 
        corwidth[i] = orgwidth[i] = round(newwidth[i]);
1289
 
 
1290
 
    check_minimum_width(t, corwidth);
1291
 
 
1292
 
    for (i = 0; i <= t->maxcol; i++) {
1293
 
        double sx = sqrt(m_entry(minv, i, i));
1294
 
        if (sx < 0.1)
1295
 
            continue;
1296
 
        if (orgwidth[i] < t->minimum_width[i] &&
1297
 
            corwidth[i] == t->minimum_width[i]) {
1298
 
            double w = (sx > 0.5) ? 0.5 : sx * 0.2;
1299
 
            sxy = 0.;
1300
 
            for (m = 0; m <= t->maxcol; m++) {
1301
 
                if (m == i)
1302
 
                    continue;
1303
 
                sxy += m_entry(minv, i, m);
1304
 
            }
1305
 
            if (sxy <= 0.) {
1306
 
                correct_table_matrix(t, i, 1, t->minimum_width[i], w);
1307
 
                corr++;
1308
 
            }
1309
 
        }
1310
 
    }
1311
 
 
1312
 
    for (k = 0; k <= cell->maxcell; k++) {
1313
 
        int nwidth = 0, mwidth;
1314
 
        double sx;
1315
 
 
1316
 
        j = cell->index[k];
1317
 
        sx = sqrt(Sxx[j]);
1318
 
        if (sx < 0.1)
1319
 
            continue;
1320
 
        bcol = cell->col[j];
1321
 
        ecol = bcol + cell->colspan[j];
1322
 
        for (i = bcol; i < ecol; i++)
1323
 
            nwidth += corwidth[i];
1324
 
        mwidth =
1325
 
            cell->minimum_width[j] - (cell->colspan[j] - 1) * t->cellspacing;
1326
 
        if (mwidth > swidth[j] && mwidth == nwidth) {
1327
 
            double w = (sx > 0.5) ? 0.5 : sx * 0.2;
1328
 
 
1329
 
            sxy = 0.;
1330
 
            for (i = bcol; i < ecol; i++) {
1331
 
                for (m = 0; m <= t->maxcol; m++) {
1332
 
                    if (m >= bcol && m < ecol)
1333
 
                        continue;
1334
 
                    sxy += m_entry(minv, i, m);
1335
 
                }
1336
 
            }
1337
 
            if (sxy <= 0.) {
1338
 
                correct_table_matrix(t, bcol, cell->colspan[j], mwidth, w);
1339
 
                corr++;
1340
 
            }
1341
 
        }
1342
 
    }
1343
 
 
1344
 
    if (itr >= MAX_ITERATION)
1345
 
        return 0;
1346
 
    else
1347
 
        return corr;
1348
 
}
1349
 
 
1350
 
#else                           /* not MATRIX */
1351
 
void
1352
 
set_table_width(struct table *t, short *newwidth, int maxwidth)
1353
 
{
1354
 
    int i, j, k, bcol, ecol;
1355
 
    struct table_cell *cell = &t->cell;
1356
 
    char *fixed;
1357
 
    int swidth, fwidth, width, nvar;
1358
 
    double s;
1359
 
    double *dwidth;
1360
 
    int try_again;
1361
 
 
1362
 
    fixed = NewAtom_N(char, t->maxcol + 1);
1363
 
    bzero(fixed, t->maxcol + 1);
1364
 
    dwidth = NewAtom_N(double, t->maxcol + 1);
1365
 
 
1366
 
    for (i = 0; i <= t->maxcol; i++) {
1367
 
        dwidth[i] = 0.0;
1368
 
        if (t->fixed_width[i] < 0) {
1369
 
            t->fixed_width[i] = -t->fixed_width[i] * maxwidth / 100;
1370
 
        }
1371
 
        if (t->fixed_width[i] > 0) {
1372
 
            newwidth[i] = t->fixed_width[i];
1373
 
            fixed[i] = 1;
1374
 
        }
1375
 
        else
1376
 
            newwidth[i] = 0;
1377
 
        if (newwidth[i] < t->minimum_width[i])
1378
 
            newwidth[i] = t->minimum_width[i];
1379
 
    }
1380
 
 
1381
 
    for (k = 0; k <= cell->maxcell; k++) {
1382
 
        j = cell->indexarray[k];
1383
 
        bcol = cell->col[j];
1384
 
        ecol = bcol + cell->colspan[j];
1385
 
 
1386
 
        if (cell->fixed_width[j] < 0)
1387
 
            cell->fixed_width[j] = -cell->fixed_width[j] * maxwidth / 100;
1388
 
 
1389
 
        swidth = 0;
1390
 
        fwidth = 0;
1391
 
        nvar = 0;
1392
 
        for (i = bcol; i < ecol; i++) {
1393
 
            if (fixed[i]) {
1394
 
                fwidth += newwidth[i];
1395
 
            }
1396
 
            else {
1397
 
                swidth += newwidth[i];
1398
 
                nvar++;
1399
 
            }
1400
 
        }
1401
 
        width = max(cell->fixed_width[j], cell->minimum_width[j])
1402
 
            - (cell->colspan[j] - 1) * t->cellspacing;
1403
 
        if (nvar > 0 && width > fwidth + swidth) {
1404
 
            s = 0.;
1405
 
            for (i = bcol; i < ecol; i++) {
1406
 
                if (!fixed[i])
1407
 
                    s += weight3(t->tabwidth[i]);
1408
 
            }
1409
 
            for (i = bcol; i < ecol; i++) {
1410
 
                if (!fixed[i])
1411
 
                    dwidth[i] = (width - fwidth) * weight3(t->tabwidth[i]) / s;
1412
 
                else
1413
 
                    dwidth[i] = (double)newwidth[i];
1414
 
            }
1415
 
            dv2sv(dwidth, newwidth, cell->colspan[j]);
1416
 
            if (cell->fixed_width[j] > 0) {
1417
 
                for (i = bcol; i < ecol; i++)
1418
 
                    fixed[i] = 1;
1419
 
            }
1420
 
        }
1421
 
    }
1422
 
 
1423
 
    do {
1424
 
        nvar = 0;
1425
 
        swidth = 0;
1426
 
        fwidth = 0;
1427
 
        for (i = 0; i <= t->maxcol; i++) {
1428
 
            if (fixed[i]) {
1429
 
                fwidth += newwidth[i];
1430
 
            }
1431
 
            else {
1432
 
                swidth += newwidth[i];
1433
 
                nvar++;
1434
 
            }
1435
 
        }
1436
 
        width = maxwidth - t->maxcol * t->cellspacing;
1437
 
        if (nvar == 0 || width <= fwidth + swidth)
1438
 
            break;
1439
 
 
1440
 
        s = 0.;
1441
 
        for (i = 0; i <= t->maxcol; i++) {
1442
 
            if (!fixed[i])
1443
 
                s += weight3(t->tabwidth[i]);
1444
 
        }
1445
 
        for (i = 0; i <= t->maxcol; i++) {
1446
 
            if (!fixed[i])
1447
 
                dwidth[i] = (width - fwidth) * weight3(t->tabwidth[i]) / s;
1448
 
            else
1449
 
                dwidth[i] = (double)newwidth[i];
1450
 
        }
1451
 
        dv2sv(dwidth, newwidth, t->maxcol + 1);
1452
 
 
1453
 
        try_again = 0;
1454
 
        for (i = 0; i <= t->maxcol; i++) {
1455
 
            if (!fixed[i]) {
1456
 
                if (newwidth[i] > t->tabwidth[i]) {
1457
 
                    newwidth[i] = t->tabwidth[i];
1458
 
                    fixed[i] = 1;
1459
 
                    try_again = 1;
1460
 
                }
1461
 
                else if (newwidth[i] < t->minimum_width[i]) {
1462
 
                    newwidth[i] = t->minimum_width[i];
1463
 
                    fixed[i] = 1;
1464
 
                    try_again = 1;
1465
 
                }
1466
 
            }
1467
 
        }
1468
 
    } while (try_again);
1469
 
}
1470
 
#endif                          /* not MATRIX */
1471
 
 
1472
 
void
1473
 
check_table_height(struct table *t)
1474
 
{
1475
 
    int i, j, k;
1476
 
    struct {
1477
 
        short *row;
1478
 
        short *rowspan;
1479
 
        short *indexarray;
1480
 
        short maxcell;
1481
 
        short size;
1482
 
        short *height;
1483
 
    } cell;
1484
 
    int space = 0;
1485
 
 
1486
 
    cell.size = 0;
1487
 
    cell.maxcell = -1;
1488
 
 
1489
 
    for (j = 0; j <= t->maxrow; j++) {
1490
 
        if (!t->tabattr[j])
1491
 
            continue;
1492
 
        for (i = 0; i <= t->maxcol; i++) {
1493
 
            int t_dep, rowspan;
1494
 
            if (t->tabattr[j][i] & (HTT_X | HTT_Y))
1495
 
                continue;
1496
 
 
1497
 
            if (t->tabdata[j][i] == NULL)
1498
 
                t_dep = 0;
1499
 
            else
1500
 
                t_dep = t->tabdata[j][i]->nitem;
1501
 
 
1502
 
            rowspan = table_rowspan(t, j, i);
1503
 
            if (rowspan > 1) {
1504
 
                int c = cell.maxcell + 1;
1505
 
                k = bsearch_2short(rowspan, cell.rowspan,
1506
 
                                   j, cell.row, t->maxrow + 1, cell.indexarray,
1507
 
                                   c);
1508
 
                if (k <= cell.maxcell) {
1509
 
                    int idx = cell.indexarray[k];
1510
 
                    if (cell.row[idx] == j && cell.rowspan[idx] == rowspan)
1511
 
                        c = idx;
1512
 
                }
1513
 
                if (c >= MAXROWCELL)
1514
 
                    continue;
1515
 
                if (c >= cell.size) {
1516
 
                    if (cell.size == 0) {
1517
 
                        cell.size = max(MAXCELL, c + 1);
1518
 
                        cell.row = NewAtom_N(short, cell.size);
1519
 
                        cell.rowspan = NewAtom_N(short, cell.size);
1520
 
                        cell.indexarray = NewAtom_N(short, cell.size);
1521
 
                        cell.height = NewAtom_N(short, cell.size);
1522
 
                    }
1523
 
                    else {
1524
 
                        cell.size = max(cell.size + MAXCELL, c + 1);
1525
 
                        cell.row = New_Reuse(short, cell.row, cell.size);
1526
 
                        cell.rowspan = New_Reuse(short, cell.rowspan,
1527
 
                                                 cell.size);
1528
 
                        cell.indexarray = New_Reuse(short, cell.indexarray,
1529
 
                                                    cell.size);
1530
 
                        cell.height = New_Reuse(short, cell.height, cell.size);
1531
 
                    }
1532
 
                }
1533
 
                if (c > cell.maxcell) {
1534
 
                    cell.maxcell++;
1535
 
                    cell.row[cell.maxcell] = j;
1536
 
                    cell.rowspan[cell.maxcell] = rowspan;
1537
 
                    cell.height[cell.maxcell] = 0;
1538
 
                    if (cell.maxcell > k) {
1539
 
                        int ii;
1540
 
                        for (ii = cell.maxcell; ii > k; ii--)
1541
 
                            cell.indexarray[ii] = cell.indexarray[ii - 1];
1542
 
                    }
1543
 
                    cell.indexarray[k] = cell.maxcell;
1544
 
                }
1545
 
 
1546
 
                if (cell.height[c] < t_dep)
1547
 
                    cell.height[c] = t_dep;
1548
 
                continue;
1549
 
            }
1550
 
            if (t->tabheight[j] < t_dep)
1551
 
                t->tabheight[j] = t_dep;
1552
 
        }
1553
 
    }
1554
 
 
1555
 
    switch (t->border_mode) {
1556
 
    case BORDER_THIN:
1557
 
    case BORDER_THICK:
1558
 
    case BORDER_NOWIN:
1559
 
        space = 1;
1560
 
        break;
1561
 
    case BORDER_NONE:
1562
 
        space = 0;
1563
 
    }
1564
 
    check_cell_width(t->tabheight, cell.height, cell.row, cell.rowspan,
1565
 
                     cell.maxcell, cell.indexarray, space, 1);
1566
 
}
1567
 
 
1568
 
#define CHECK_MINIMUM   1
1569
 
#define CHECK_FIXED     2
1570
 
 
1571
 
int
1572
 
get_table_width(struct table *t, short *orgwidth, short *cellwidth, int flag)
1573
 
{
1574
 
#ifdef __GNUC__
1575
 
    short newwidth[t->maxcol + 1];
1576
 
#else                           /* not __GNUC__ */
1577
 
    short newwidth[MAXCOL];
1578
 
#endif                          /* not __GNUC__ */
1579
 
    int i;
1580
 
    int swidth;
1581
 
    struct table_cell *cell = &t->cell;
1582
 
    int rulewidth = table_rule_width(t);
1583
 
 
1584
 
    for (i = 0; i <= t->maxcol; i++)
1585
 
        newwidth[i] = max(orgwidth[i], 0);
1586
 
 
1587
 
    if (flag & CHECK_FIXED) {
1588
 
#ifdef __GNUC__
1589
 
        short ccellwidth[cell->maxcell + 1];
1590
 
#else                           /* not __GNUC__ */
1591
 
        short ccellwidth[MAXCELL];
1592
 
#endif                          /* not __GNUC__ */
1593
 
        for (i = 0; i <= t->maxcol; i++) {
1594
 
            if (newwidth[i] < t->fixed_width[i])
1595
 
                newwidth[i] = t->fixed_width[i];
1596
 
        }
1597
 
        for (i = 0; i <= cell->maxcell; i++) {
1598
 
            ccellwidth[i] = cellwidth[i];
1599
 
            if (ccellwidth[i] < cell->fixed_width[i])
1600
 
                ccellwidth[i] = cell->fixed_width[i];
1601
 
        }
1602
 
        check_cell_width(newwidth, ccellwidth, cell->col, cell->colspan,
1603
 
                         cell->maxcell, cell->index, t->cellspacing, 0);
1604
 
    }
1605
 
    else {
1606
 
        check_cell_width(newwidth, cellwidth, cell->col, cell->colspan,
1607
 
                         cell->maxcell, cell->index, t->cellspacing, 0);
1608
 
    }
1609
 
    if (flag & CHECK_MINIMUM)
1610
 
        check_minimum_width(t, newwidth);
1611
 
 
1612
 
    swidth = 0;
1613
 
    for (i = 0; i <= t->maxcol; i++) {
1614
 
        swidth += ceil_at_intervals(newwidth[i], rulewidth);
1615
 
    }
1616
 
    swidth += table_border_width(t);
1617
 
    return swidth;
1618
 
}
1619
 
 
1620
 
#define minimum_table_width(t)\
1621
 
(get_table_width(t,t->minimum_width,t->cell.minimum_width,0))
1622
 
#define maximum_table_width(t)\
1623
 
  (get_table_width(t,t->tabwidth,t->cell.width,CHECK_FIXED))
1624
 
#define fixed_table_width(t)\
1625
 
  (get_table_width(t,t->fixed_width,t->cell.fixed_width,CHECK_MINIMUM))
1626
 
 
1627
 
void
1628
 
renderCoTable(struct table *tbl, int maxlimit)
1629
 
{
1630
 
    struct readbuffer obuf;
1631
 
    struct html_feed_environ h_env;
1632
 
    struct environment envs[MAX_ENV_LEVEL];
1633
 
    struct table *t;
1634
 
    int i, col, row;
1635
 
    int indent, maxwidth;
1636
 
 
1637
 
    for (i = 0; i < tbl->ntable; i++) {
1638
 
        t = tbl->tables[i].ptr;
1639
 
        col = tbl->tables[i].col;
1640
 
        row = tbl->tables[i].row;
1641
 
        indent = tbl->tables[i].indent;
1642
 
 
1643
 
        init_henv(&h_env, &obuf, envs, MAX_ENV_LEVEL, tbl->tables[i].buf,
1644
 
                  get_spec_cell_width(tbl, row, col), indent);
1645
 
        check_row(tbl, row);
1646
 
        if (h_env.limit > maxlimit)
1647
 
            h_env.limit = maxlimit;
1648
 
        if (t->total_width == 0)
1649
 
            maxwidth = h_env.limit - indent;
1650
 
        else if (t->total_width > 0)
1651
 
            maxwidth = t->total_width;
1652
 
        else
1653
 
            maxwidth = t->total_width = -t->total_width * h_env.limit / 100;
1654
 
        renderTable(t, maxwidth, &h_env);
1655
 
    }
1656
 
}
1657
 
 
1658
 
static void
1659
 
make_caption(struct table *t, struct html_feed_environ *h_env)
1660
 
{
1661
 
    struct html_feed_environ henv;
1662
 
    struct readbuffer obuf;
1663
 
    struct environment envs[MAX_ENV_LEVEL];
1664
 
    int limit;
1665
 
 
1666
 
    if (t->caption->length <= 0)
1667
 
        return;
1668
 
 
1669
 
    if (t->total_width > 0)
1670
 
        limit = t->total_width;
1671
 
    else
1672
 
        limit = h_env->limit;
1673
 
    init_henv(&henv, &obuf, envs, MAX_ENV_LEVEL, newTextLineList(),
1674
 
              limit, h_env->envs[h_env->envc].indent);
1675
 
    HTMLlineproc1("<center>", &henv);
1676
 
    HTMLlineproc0(t->caption->ptr, &henv, FALSE);
1677
 
    HTMLlineproc1("</center>", &henv);
1678
 
 
1679
 
    if (t->total_width < henv.maxlimit)
1680
 
        t->total_width = henv.maxlimit;
1681
 
    limit = h_env->limit;
1682
 
    h_env->limit = t->total_width;
1683
 
    HTMLlineproc1("<center>", h_env);
1684
 
    HTMLlineproc0(t->caption->ptr, h_env, FALSE);
1685
 
    HTMLlineproc1("</center>", h_env);
1686
 
    h_env->limit = limit;
1687
 
}
1688
 
 
1689
 
void
1690
 
renderTable(struct table *t, int max_width, struct html_feed_environ *h_env)
1691
 
{
1692
 
    int i, j, w, r, h;
1693
 
    Str renderbuf;
1694
 
    short new_tabwidth[MAXCOL];
1695
 
#ifdef MATRIX
1696
 
    int itr;
1697
 
    VEC *newwidth;
1698
 
    MAT *mat, *minv;
1699
 
    PERM *pivot;
1700
 
#endif                          /* MATRIX */
1701
 
    int width;
1702
 
    int rulewidth;
1703
 
    Str vrulea = NULL, vruleb = NULL, vrulec = NULL;
1704
 
#ifdef ID_EXT
1705
 
    Str idtag;
1706
 
#endif                          /* ID_EXT */
1707
 
 
1708
 
    t->total_height = 0;
1709
 
    if (t->maxcol < 0) {
1710
 
        make_caption(t, h_env);
1711
 
        return;
1712
 
    }
1713
 
 
1714
 
    if (t->sloppy_width > max_width)
1715
 
        max_width = t->sloppy_width;
1716
 
 
1717
 
    rulewidth = table_rule_width(t);
1718
 
 
1719
 
    max_width -= table_border_width(t);
1720
 
 
1721
 
    if (rulewidth > 1)
1722
 
        max_width = floor_at_intervals(max_width, rulewidth);
1723
 
 
1724
 
    if (max_width < rulewidth)
1725
 
        max_width = rulewidth;
1726
 
 
1727
 
    check_maximum_width(t);
1728
 
 
1729
 
#ifdef MATRIX
1730
 
    if (t->maxcol == 0) {
1731
 
        if (t->tabwidth[0] > max_width)
1732
 
            t->tabwidth[0] = max_width;
1733
 
        if (t->total_width > 0)
1734
 
            t->tabwidth[0] = max_width;
1735
 
        else if (t->fixed_width[0] > 0)
1736
 
            t->tabwidth[0] = t->fixed_width[0];
1737
 
        if (t->tabwidth[0] < t->minimum_width[0])
1738
 
            t->tabwidth[0] = t->minimum_width[0];
1739
 
    }
1740
 
    else {
1741
 
        set_table_matrix(t, max_width);
1742
 
 
1743
 
        itr = 0;
1744
 
        mat = m_get(t->maxcol + 1, t->maxcol + 1);
1745
 
        pivot = px_get(t->maxcol + 1);
1746
 
        newwidth = v_get(t->maxcol + 1);
1747
 
        minv = m_get(t->maxcol + 1, t->maxcol + 1);
1748
 
        do {
1749
 
            m_copy(t->matrix, mat);
1750
 
            LUfactor(mat, pivot);
1751
 
            LUsolve(mat, pivot, t->vector, newwidth);
1752
 
            LUinverse(mat, pivot, minv);
1753
 
#ifdef TABLE_DEBUG
1754
 
            set_integered_width(t, newwidth->ve, new_tabwidth);
1755
 
            fprintf(stderr, "itr=%d\n", itr);
1756
 
            fprintf(stderr, "max_width=%d\n", max_width);
1757
 
            fprintf(stderr, "minimum : ");
1758
 
            for (i = 0; i <= t->maxcol; i++)
1759
 
                fprintf(stderr, "%2d ", t->minimum_width[i]);
1760
 
            fprintf(stderr, "\nfixed : ");
1761
 
            for (i = 0; i <= t->maxcol; i++)
1762
 
                fprintf(stderr, "%2d ", t->fixed_width[i]);
1763
 
            fprintf(stderr, "\ndecided : ");
1764
 
            for (i = 0; i <= t->maxcol; i++)
1765
 
                fprintf(stderr, "%2d ", new_tabwidth[i]);
1766
 
            fprintf(stderr, "\n");
1767
 
#endif                          /* TABLE_DEBUG */
1768
 
            itr++;
1769
 
 
1770
 
        } while (check_table_width(t, newwidth->ve, minv, itr));
1771
 
        set_integered_width(t, newwidth->ve, new_tabwidth);
1772
 
        check_minimum_width(t, new_tabwidth);
1773
 
        v_free(newwidth);
1774
 
        px_free(pivot);
1775
 
        m_free(mat);
1776
 
        m_free(minv);
1777
 
        m_free(t->matrix);
1778
 
        v_free(t->vector);
1779
 
        for (i = 0; i <= t->maxcol; i++) {
1780
 
            t->tabwidth[i] = new_tabwidth[i];
1781
 
        }
1782
 
    }
1783
 
#else                           /* not MATRIX */
1784
 
    set_table_width(t, new_tabwidth, max_width);
1785
 
    for (i = 0; i <= t->maxcol; i++) {
1786
 
        t->tabwidth[i] = new_tabwidth[i];
1787
 
    }
1788
 
#endif                          /* not MATRIX */
1789
 
 
1790
 
    check_minimum_width(t, t->tabwidth);
1791
 
    for (i = 0; i <= t->maxcol; i++)
1792
 
        t->tabwidth[i] = ceil_at_intervals(t->tabwidth[i], rulewidth);
1793
 
 
1794
 
    renderCoTable(t, h_env->limit);
1795
 
 
1796
 
    for (i = 0; i <= t->maxcol; i++) {
1797
 
        for (j = 0; j <= t->maxrow; j++) {
1798
 
            check_row(t, j);
1799
 
            if (t->tabattr[j][i] & HTT_Y)
1800
 
                continue;
1801
 
            do_refill(t, j, i, h_env->limit);
1802
 
        }
1803
 
    }
1804
 
 
1805
 
    check_minimum_width(t, t->tabwidth);
1806
 
    t->total_width = 0;
1807
 
    for (i = 0; i <= t->maxcol; i++) {
1808
 
        t->tabwidth[i] = ceil_at_intervals(t->tabwidth[i], rulewidth);
1809
 
        t->total_width += t->tabwidth[i];
1810
 
    }
1811
 
 
1812
 
    t->total_width += table_border_width(t);
1813
 
 
1814
 
    check_table_height(t);
1815
 
 
1816
 
    for (i = 0; i <= t->maxcol; i++) {
1817
 
        for (j = 0; j <= t->maxrow; j++) {
1818
 
            TextLineList *l;
1819
 
            int k;
1820
 
            if ((t->tabattr[j][i] & HTT_Y) ||
1821
 
                (t->tabattr[j][i] & HTT_TOP) || (t->tabdata[j][i] == NULL))
1822
 
                continue;
1823
 
            h = t->tabheight[j];
1824
 
            for (k = j + 1; k <= t->maxrow; k++) {
1825
 
                if (!(t->tabattr[k][i] & HTT_Y))
1826
 
                    break;
1827
 
                h += t->tabheight[k];
1828
 
                switch (t->border_mode) {
1829
 
                case BORDER_THIN:
1830
 
                case BORDER_THICK:
1831
 
                case BORDER_NOWIN:
1832
 
                    h += 1;
1833
 
                    break;
1834
 
                }
1835
 
            }
1836
 
            h -= t->tabdata[j][i]->nitem;
1837
 
            if (t->tabattr[j][i] & HTT_MIDDLE)
1838
 
                h /= 2;
1839
 
            if (h <= 0)
1840
 
                continue;
1841
 
            l = newTextLineList();
1842
 
            for (k = 0; k < h; k++)
1843
 
                pushTextLine(l, newTextLine(NULL, 0));
1844
 
            t->tabdata[j][i] = appendGeneralList((GeneralList *)l,
1845
 
                                                 t->tabdata[j][i]);
1846
 
        }
1847
 
    }
1848
 
 
1849
 
    /* table output */
1850
 
    width = t->total_width;
1851
 
 
1852
 
    make_caption(t, h_env);
1853
 
 
1854
 
    HTMLlineproc1("<pre for_table>", h_env);
1855
 
#ifdef ID_EXT
1856
 
    if (t->id != NULL) {
1857
 
        idtag = Sprintf("<_id id=\"%s\">", html_quote((t->id)->ptr));
1858
 
        HTMLlineproc1(idtag->ptr, h_env);
1859
 
    }
1860
 
#endif                          /* ID_EXT */
1861
 
    switch (t->border_mode) {
1862
 
    case BORDER_THIN:
1863
 
    case BORDER_THICK:
1864
 
        renderbuf = Strnew();
1865
 
        print_sep(t, -1, T_TOP, t->maxcol, renderbuf);
1866
 
        push_render_image(renderbuf, width, t->total_width, h_env);
1867
 
        t->total_height += 1;
1868
 
        break;
1869
 
    }
1870
 
    vruleb = Strnew();
1871
 
    switch (t->border_mode) {
1872
 
    case BORDER_THIN:
1873
 
    case BORDER_THICK:
1874
 
        vrulea = Strnew();
1875
 
        vrulec = Strnew();
1876
 
        push_symbol(vrulea, TK_VERTICALBAR(t->border_mode), symbol_width, 1);
1877
 
        for (i = 0; i < t->cellpadding; i++) {
1878
 
            Strcat_char(vrulea, ' ');
1879
 
            Strcat_char(vruleb, ' ');
1880
 
            Strcat_char(vrulec, ' ');
1881
 
        }
1882
 
        push_symbol(vrulec, TK_VERTICALBAR(t->border_mode), symbol_width, 1);
1883
 
    case BORDER_NOWIN:
1884
 
        push_symbol(vruleb, TK_VERTICALBAR(BORDER_THIN), symbol_width, 1);
1885
 
        for (i = 0; i < t->cellpadding; i++)
1886
 
            Strcat_char(vruleb, ' ');
1887
 
        break;
1888
 
    case BORDER_NONE:
1889
 
        for (i = 0; i < t->cellspacing; i++)
1890
 
            Strcat_char(vruleb, ' ');
1891
 
    }
1892
 
 
1893
 
    for (r = 0; r <= t->maxrow; r++) {
1894
 
        for (h = 0; h < t->tabheight[r]; h++) {
1895
 
            renderbuf = Strnew();
1896
 
            if (t->border_mode == BORDER_THIN
1897
 
                || t->border_mode == BORDER_THICK)
1898
 
                Strcat(renderbuf, vrulea);
1899
 
#ifdef ID_EXT
1900
 
            if (t->tridvalue[r] != NULL && h == 0) {
1901
 
                idtag = Sprintf("<_id id=\"%s\">",
1902
 
                                html_quote((t->tridvalue[r])->ptr));
1903
 
                Strcat(renderbuf, idtag);
1904
 
            }
1905
 
#endif                          /* ID_EXT */
1906
 
            for (i = 0; i <= t->maxcol; i++) {
1907
 
                check_row(t, r);
1908
 
#ifdef ID_EXT
1909
 
                if (t->tabidvalue[r][i] != NULL && h == 0) {
1910
 
                    idtag = Sprintf("<_id id=\"%s\">",
1911
 
                                    html_quote((t->tabidvalue[r][i])->ptr));
1912
 
                    Strcat(renderbuf, idtag);
1913
 
                }
1914
 
#endif                          /* ID_EXT */
1915
 
                if (!(t->tabattr[r][i] & HTT_X)) {
1916
 
                    w = t->tabwidth[i];
1917
 
                    for (j = i + 1;
1918
 
                         j <= t->maxcol && (t->tabattr[r][j] & HTT_X); j++)
1919
 
                        w += t->tabwidth[j] + t->cellspacing;
1920
 
                    if (t->tabattr[r][i] & HTT_Y) {
1921
 
                        for (j = r - 1; j >= 0 && t->tabattr[j]
1922
 
                             && (t->tabattr[j][i] & HTT_Y); j--) ;
1923
 
                        print_item(t, j, i, w, renderbuf);
1924
 
                    }
1925
 
                    else
1926
 
                        print_item(t, r, i, w, renderbuf);
1927
 
                }
1928
 
                if (i < t->maxcol && !(t->tabattr[r][i + 1] & HTT_X))
1929
 
                    Strcat(renderbuf, vruleb);
1930
 
            }
1931
 
            switch (t->border_mode) {
1932
 
            case BORDER_THIN:
1933
 
            case BORDER_THICK:
1934
 
                Strcat(renderbuf, vrulec);
1935
 
                t->total_height += 1;
1936
 
                break;
1937
 
            }
1938
 
            push_render_image(renderbuf, width, t->total_width, h_env);
1939
 
        }
1940
 
        if (r < t->maxrow && t->border_mode != BORDER_NONE) {
1941
 
            renderbuf = Strnew();
1942
 
            print_sep(t, r, T_MIDDLE, t->maxcol, renderbuf);
1943
 
            push_render_image(renderbuf, width, t->total_width, h_env);
1944
 
        }
1945
 
        t->total_height += t->tabheight[r];
1946
 
    }
1947
 
    switch (t->border_mode) {
1948
 
    case BORDER_THIN:
1949
 
    case BORDER_THICK:
1950
 
        renderbuf = Strnew();
1951
 
        print_sep(t, t->maxrow, T_BOTTOM, t->maxcol, renderbuf);
1952
 
        push_render_image(renderbuf, width, t->total_width, h_env);
1953
 
        t->total_height += 1;
1954
 
        break;
1955
 
    }
1956
 
    if (t->total_height == 0) {
1957
 
       renderbuf = Strnew_charp(" ");
1958
 
        t->total_height++;
1959
 
        t->total_width = 1;
1960
 
        push_render_image(renderbuf, 1, t->total_width, h_env);
1961
 
    }
1962
 
    HTMLlineproc1("</pre>", h_env);
1963
 
}
1964
 
 
1965
 
#ifdef TABLE_NO_COMPACT
1966
 
#define THR_PADDING 2
1967
 
#else
1968
 
#define THR_PADDING 4
1969
 
#endif
1970
 
 
1971
 
struct table *
1972
 
begin_table(int border, int spacing, int padding, int vspace)
1973
 
{
1974
 
    struct table *t;
1975
 
    int mincell = minimum_cellspacing(border);
1976
 
    int rcellspacing;
1977
 
    int mincell_pixels = round(mincell * pixel_per_char);
1978
 
    int ppc = round(pixel_per_char);
1979
 
 
1980
 
    t = newTable();
1981
 
    t->row = t->col = -1;
1982
 
    t->maxcol = -1;
1983
 
    t->maxrow = -1;
1984
 
    t->border_mode = border;
1985
 
    t->flag = 0;
1986
 
    if (border == BORDER_NOWIN)
1987
 
        t->flag |= TBL_EXPAND_OK;
1988
 
 
1989
 
    rcellspacing = spacing + 2 * padding;
1990
 
    switch (border) {
1991
 
    case BORDER_THIN:
1992
 
    case BORDER_THICK:
1993
 
    case BORDER_NOWIN:
1994
 
        t->cellpadding = padding - (mincell_pixels - 4) / 2;
1995
 
        break;
1996
 
    case BORDER_NONE:
1997
 
        t->cellpadding = rcellspacing - mincell_pixels;
1998
 
    }
1999
 
    if (t->cellpadding >= ppc)
2000
 
        t->cellpadding /= ppc;
2001
 
    else if (t->cellpadding > 0)
2002
 
        t->cellpadding = 1;
2003
 
    else
2004
 
        t->cellpadding = 0;
2005
 
 
2006
 
    switch (border) {
2007
 
    case BORDER_THIN:
2008
 
    case BORDER_THICK:
2009
 
    case BORDER_NOWIN:
2010
 
        t->cellspacing = 2 * t->cellpadding + mincell;
2011
 
        break;
2012
 
    case BORDER_NONE:
2013
 
        t->cellspacing = t->cellpadding + mincell;
2014
 
    }
2015
 
 
2016
 
    if (border == BORDER_NONE) {
2017
 
        if (rcellspacing / 2 + vspace <= 1)
2018
 
            t->vspace = 0;
2019
 
        else
2020
 
            t->vspace = 1;
2021
 
    }
2022
 
    else {
2023
 
        if (vspace < ppc)
2024
 
            t->vspace = 0;
2025
 
        else
2026
 
            t->vspace = 1;
2027
 
    }
2028
 
 
2029
 
    if (border == BORDER_NONE) {
2030
 
        if (rcellspacing <= THR_PADDING)
2031
 
            t->vcellpadding = 0;
2032
 
        else
2033
 
            t->vcellpadding = 1;
2034
 
    }
2035
 
    else {
2036
 
        if (padding < 2 * ppc - 2)
2037
 
            t->vcellpadding = 0;
2038
 
        else
2039
 
            t->vcellpadding = 1;
2040
 
    }
2041
 
 
2042
 
    return t;
2043
 
}
2044
 
 
2045
 
void
2046
 
end_table(struct table *tbl)
2047
 
{
2048
 
    struct table_cell *cell = &tbl->cell;
2049
 
    int i, rulewidth = table_rule_width(tbl);
2050
 
    if (rulewidth > 1) {
2051
 
        if (tbl->total_width > 0)
2052
 
            tbl->total_width = ceil_at_intervals(tbl->total_width, rulewidth);
2053
 
        for (i = 0; i <= tbl->maxcol; i++) {
2054
 
            tbl->minimum_width[i] =
2055
 
                ceil_at_intervals(tbl->minimum_width[i], rulewidth);
2056
 
            tbl->tabwidth[i] = ceil_at_intervals(tbl->tabwidth[i], rulewidth);
2057
 
            if (tbl->fixed_width[i] > 0)
2058
 
                tbl->fixed_width[i] =
2059
 
                    ceil_at_intervals(tbl->fixed_width[i], rulewidth);
2060
 
        }
2061
 
        for (i = 0; i <= cell->maxcell; i++) {
2062
 
            cell->minimum_width[i] =
2063
 
                ceil_at_intervals(cell->minimum_width[i], rulewidth);
2064
 
            cell->width[i] = ceil_at_intervals(cell->width[i], rulewidth);
2065
 
            if (cell->fixed_width[i] > 0)
2066
 
                cell->fixed_width[i] =
2067
 
                    ceil_at_intervals(cell->fixed_width[i], rulewidth);
2068
 
        }
2069
 
    }
2070
 
    tbl->sloppy_width = fixed_table_width(tbl);
2071
 
    if (tbl->total_width > tbl->sloppy_width)
2072
 
        tbl->sloppy_width = tbl->total_width;
2073
 
}
2074
 
 
2075
 
static void
2076
 
check_minimum0(struct table *t, int min)
2077
 
{
2078
 
    int i, w, ww;
2079
 
    struct table_cell *cell;
2080
 
 
2081
 
    if (t->col < 0)
2082
 
        return;
2083
 
    if (t->tabwidth[t->col] < 0)
2084
 
        return;
2085
 
    check_row(t, t->row);
2086
 
    w = table_colspan(t, t->row, t->col);
2087
 
    min += t->indent;
2088
 
    if (w == 1)
2089
 
        ww = min;
2090
 
    else {
2091
 
        cell = &t->cell;
2092
 
        ww = 0;
2093
 
        if (cell->icell >= 0 && cell->minimum_width[cell->icell] < min)
2094
 
            cell->minimum_width[cell->icell] = min;
2095
 
    }
2096
 
    for (i = t->col;
2097
 
         i <= t->maxcol && (i == t->col || (t->tabattr[t->row][i] & HTT_X));
2098
 
         i++) {
2099
 
        if (t->minimum_width[i] < ww)
2100
 
            t->minimum_width[i] = ww;
2101
 
    }
2102
 
}
2103
 
 
2104
 
static int
2105
 
setwidth0(struct table *t, struct table_mode *mode)
2106
 
{
2107
 
    int w;
2108
 
    int width = t->tabcontentssize;
2109
 
    struct table_cell *cell = &t->cell;
2110
 
 
2111
 
    if (t->col < 0)
2112
 
        return -1;
2113
 
    if (t->tabwidth[t->col] < 0)
2114
 
        return -1;
2115
 
    check_row(t, t->row);
2116
 
    if (t->linfo.prev_spaces > 0)
2117
 
        width -= t->linfo.prev_spaces;
2118
 
    w = table_colspan(t, t->row, t->col);
2119
 
    if (w == 1) {
2120
 
        if (t->tabwidth[t->col] < width)
2121
 
            t->tabwidth[t->col] = width;
2122
 
    }
2123
 
    else if (cell->icell >= 0) {
2124
 
        if (cell->width[cell->icell] < width)
2125
 
            cell->width[cell->icell] = width;
2126
 
    }
2127
 
    return width;
2128
 
}
2129
 
 
2130
 
static void
2131
 
setwidth(struct table *t, struct table_mode *mode)
2132
 
{
2133
 
    int width = setwidth0(t, mode);
2134
 
    if (width < 0)
2135
 
        return;
2136
 
#ifdef NOWRAP
2137
 
    if (t->tabattr[t->row][t->col] & HTT_NOWRAP)
2138
 
        check_minimum0(t, width);
2139
 
#endif                          /* NOWRAP */
2140
 
    if (mode->pre_mode & (TBLM_NOBR | TBLM_PRE | TBLM_PRE_INT) &&
2141
 
        mode->nobr_offset >= 0)
2142
 
        check_minimum0(t, width - mode->nobr_offset);
2143
 
}
2144
 
 
2145
 
static void
2146
 
addcontentssize(struct table *t, int width)
2147
 
{
2148
 
 
2149
 
    if (t->col < 0)
2150
 
        return;
2151
 
    if (t->tabwidth[t->col] < 0)
2152
 
        return;
2153
 
    check_row(t, t->row);
2154
 
    t->tabcontentssize += width;
2155
 
}
2156
 
 
2157
 
static void table_close_anchor0(struct table *tbl, struct table_mode *mode);
2158
 
 
2159
 
static void
2160
 
clearcontentssize(struct table *t, struct table_mode *mode)
2161
 
{
2162
 
    table_close_anchor0(t, mode);
2163
 
    mode->nobr_offset = 0;
2164
 
    t->linfo.prev_spaces = -1;
2165
 
    set_space_to_prevchar(t->linfo.prevchar);
2166
 
    t->linfo.prev_ctype = PC_ASCII;
2167
 
    t->linfo.length = 0;
2168
 
    t->tabcontentssize = 0;
2169
 
}
2170
 
 
2171
 
static void
2172
 
begin_cell(struct table *t, struct table_mode *mode)
2173
 
{
2174
 
    clearcontentssize(t, mode);
2175
 
    mode->indent_level = 0;
2176
 
    mode->nobr_level = 0;
2177
 
    mode->pre_mode = 0;
2178
 
    t->indent = 0;
2179
 
    t->flag |= TBL_IN_COL;
2180
 
 
2181
 
    if (t->suspended_data) {
2182
 
        check_row(t, t->row);
2183
 
        if (t->tabdata[t->row][t->col] == NULL)
2184
 
            t->tabdata[t->row][t->col] = newGeneralList();
2185
 
        appendGeneralList(t->tabdata[t->row][t->col],
2186
 
                          (GeneralList *)t->suspended_data);
2187
 
        t->suspended_data = NULL;
2188
 
    }
2189
 
}
2190
 
 
2191
 
void
2192
 
check_rowcol(struct table *tbl, struct table_mode *mode)
2193
 
{
2194
 
    int row = tbl->row, col = tbl->col;
2195
 
 
2196
 
    if (!(tbl->flag & TBL_IN_ROW)) {
2197
 
        tbl->flag |= TBL_IN_ROW;
2198
 
        tbl->row++;
2199
 
        if (tbl->row > tbl->maxrow)
2200
 
            tbl->maxrow = tbl->row;
2201
 
        tbl->col = -1;
2202
 
    }
2203
 
    if (tbl->row == -1)
2204
 
        tbl->row = 0;
2205
 
    if (tbl->col == -1)
2206
 
        tbl->col = 0;
2207
 
 
2208
 
    for (;; tbl->row++) {
2209
 
        check_row(tbl, tbl->row);
2210
 
        for (; tbl->col < MAXCOL &&
2211
 
             tbl->tabattr[tbl->row][tbl->col] & (HTT_X | HTT_Y); tbl->col++) ;
2212
 
        if (tbl->col < MAXCOL)
2213
 
            break;
2214
 
        tbl->col = 0;
2215
 
    }
2216
 
    if (tbl->row > tbl->maxrow)
2217
 
        tbl->maxrow = tbl->row;
2218
 
    if (tbl->col > tbl->maxcol)
2219
 
        tbl->maxcol = tbl->col;
2220
 
 
2221
 
    if (tbl->row != row || tbl->col != col)
2222
 
        begin_cell(tbl, mode);
2223
 
    tbl->flag |= TBL_IN_COL;
2224
 
}
2225
 
 
2226
 
int
2227
 
skip_space(struct table *t, char *line, struct table_linfo *linfo,
2228
 
           int checkminimum)
2229
 
{
2230
 
    int skip = 0, s = linfo->prev_spaces;
2231
 
    Lineprop ctype, prev_ctype = linfo->prev_ctype;
2232
 
    Str prevchar = linfo->prevchar;
2233
 
    int w = linfo->length;
2234
 
    int min = 1;
2235
 
 
2236
 
    if (*line == '<' && line[strlen(line) - 1] == '>') {
2237
 
        if (checkminimum)
2238
 
            check_minimum0(t, visible_length(line));
2239
 
        return 0;
2240
 
    }
2241
 
 
2242
 
    while (*line) {
2243
 
        char *save = line, *c = line;
2244
 
        int ec, len, wlen, plen;
2245
 
        ctype = get_mctype(line);
2246
 
        len = get_mcwidth(line);
2247
 
        wlen = plen = get_mclen(line);
2248
 
 
2249
 
        if (min < w)
2250
 
            min = w;
2251
 
        if (ctype == PC_ASCII && IS_SPACE(*c)) {
2252
 
            w = 0;
2253
 
            s++;
2254
 
        }
2255
 
        else {
2256
 
            if (*c == '&') {
2257
 
                ec = getescapechar(&line);
2258
 
                if (ec >= 0) {
2259
 
                    c = conv_entity(ec);
2260
 
                    ctype = get_mctype(c);
2261
 
                    len = get_strwidth(c);
2262
 
                    wlen = line - save;
2263
 
                    plen = get_mclen(c);
2264
 
                }
2265
 
            }
2266
 
            if (prevchar->length && is_boundary((unsigned char *)prevchar->ptr,
2267
 
                                                (unsigned char *)c)) {
2268
 
                w = len;
2269
 
            }
2270
 
            else {
2271
 
                w += len;
2272
 
            }
2273
 
            if (s > 0) {
2274
 
#ifdef USE_M17N
2275
 
                if (ctype == PC_KANJI1 && prev_ctype == PC_KANJI1)
2276
 
                    skip += s;
2277
 
                else
2278
 
#endif
2279
 
                    skip += s - 1;
2280
 
            }
2281
 
            s = 0;
2282
 
            prev_ctype = ctype;
2283
 
        }
2284
 
        set_prevchar(prevchar, c, plen);
2285
 
        line = save + wlen;
2286
 
    }
2287
 
    if (s > 1) {
2288
 
        skip += s - 1;
2289
 
        linfo->prev_spaces = 1;
2290
 
    }
2291
 
    else {
2292
 
        linfo->prev_spaces = s;
2293
 
    }
2294
 
    linfo->prev_ctype = prev_ctype;
2295
 
    linfo->prevchar = prevchar;
2296
 
 
2297
 
    if (checkminimum) {
2298
 
        if (min < w)
2299
 
            min = w;
2300
 
        linfo->length = w;
2301
 
        check_minimum0(t, min);
2302
 
    }
2303
 
    return skip;
2304
 
}
2305
 
 
2306
 
static void
2307
 
feed_table_inline_tag(struct table *tbl,
2308
 
                      char *line, struct table_mode *mode, int width)
2309
 
{
2310
 
    check_rowcol(tbl, mode);
2311
 
    pushdata(tbl, tbl->row, tbl->col, line);
2312
 
    if (width >= 0) {
2313
 
        check_minimum0(tbl, width);
2314
 
        addcontentssize(tbl, width);
2315
 
        setwidth(tbl, mode);
2316
 
    }
2317
 
}
2318
 
 
2319
 
static void
2320
 
feed_table_block_tag(struct table *tbl,
2321
 
                     char *line, struct table_mode *mode, int indent, int cmd)
2322
 
{
2323
 
    int offset;
2324
 
    if (mode->indent_level <= 0 && indent == -1)
2325
 
        return;
2326
 
    setwidth(tbl, mode);
2327
 
    feed_table_inline_tag(tbl, line, mode, -1);
2328
 
    clearcontentssize(tbl, mode);
2329
 
    if (indent == 1) {
2330
 
        mode->indent_level++;
2331
 
        if (mode->indent_level <= MAX_INDENT_LEVEL)
2332
 
            tbl->indent += INDENT_INCR;
2333
 
    }
2334
 
    else if (indent == -1) {
2335
 
        mode->indent_level--;
2336
 
        if (mode->indent_level < MAX_INDENT_LEVEL)
2337
 
            tbl->indent -= INDENT_INCR;
2338
 
    }
2339
 
    offset = tbl->indent;
2340
 
    if (cmd == HTML_DT) {
2341
 
        if (mode->indent_level > 0 && mode->indent_level <= MAX_INDENT_LEVEL)
2342
 
            offset -= INDENT_INCR;
2343
 
    }
2344
 
    if (tbl->indent > 0) {
2345
 
        check_minimum0(tbl, 0);
2346
 
        addcontentssize(tbl, offset);
2347
 
    }
2348
 
}
2349
 
 
2350
 
static void
2351
 
table_close_select(struct table *tbl, struct table_mode *mode, int width)
2352
 
{
2353
 
    Str tmp = process_n_select();
2354
 
    mode->pre_mode &= ~TBLM_INSELECT;
2355
 
    mode->end_tag = 0;
2356
 
    feed_table1(tbl, tmp, mode, width);
2357
 
}
2358
 
 
2359
 
static void
2360
 
table_close_textarea(struct table *tbl, struct table_mode *mode, int width)
2361
 
{
2362
 
    Str tmp = process_n_textarea();
2363
 
    mode->pre_mode &= ~TBLM_INTXTA;
2364
 
    mode->end_tag = 0;
2365
 
    feed_table1(tbl, tmp, mode, width);
2366
 
}
2367
 
 
2368
 
static void
2369
 
table_close_anchor0(struct table *tbl, struct table_mode *mode)
2370
 
{
2371
 
    if (!(mode->pre_mode & TBLM_ANCHOR))
2372
 
        return;
2373
 
    mode->pre_mode &= ~TBLM_ANCHOR;
2374
 
    if (tbl->tabcontentssize == mode->anchor_offset) {
2375
 
        check_minimum0(tbl, 1);
2376
 
        addcontentssize(tbl, 1);
2377
 
        setwidth(tbl, mode);
2378
 
    }
2379
 
    else if (tbl->linfo.prev_spaces > 0 &&
2380
 
             tbl->tabcontentssize - 1 == mode->anchor_offset) {
2381
 
        if (tbl->linfo.prev_spaces > 0)
2382
 
            tbl->linfo.prev_spaces = -1;
2383
 
    }
2384
 
}
2385
 
 
2386
 
#define TAG_ACTION_NONE 0
2387
 
#define TAG_ACTION_FEED 1
2388
 
#define TAG_ACTION_TABLE 2
2389
 
#define TAG_ACTION_N_TABLE 3
2390
 
#define TAG_ACTION_PLAIN 4
2391
 
 
2392
 
#define CASE_TABLE_TAG \
2393
 
        case HTML_TABLE:\
2394
 
        case HTML_N_TABLE:\
2395
 
        case HTML_TR:\
2396
 
        case HTML_N_TR:\
2397
 
        case HTML_TD:\
2398
 
        case HTML_N_TD:\
2399
 
        case HTML_TH:\
2400
 
        case HTML_N_TH:\
2401
 
        case HTML_THEAD:\
2402
 
        case HTML_N_THEAD:\
2403
 
        case HTML_TBODY:\
2404
 
        case HTML_N_TBODY:\
2405
 
        case HTML_TFOOT:\
2406
 
        case HTML_N_TFOOT:\
2407
 
        case HTML_COLGROUP:\
2408
 
        case HTML_N_COLGROUP:\
2409
 
        case HTML_COL
2410
 
 
2411
 
#define ATTR_ROWSPAN_MAX 32766
2412
 
 
2413
 
static int
2414
 
feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
2415
 
               int width, struct parsed_tag *tag)
2416
 
{
2417
 
    int cmd;
2418
 
#ifdef ID_EXT
2419
 
    char *p;
2420
 
#endif
2421
 
    struct table_cell *cell = &tbl->cell;
2422
 
    int colspan, rowspan;
2423
 
    int col, prev_col;
2424
 
    int i, j, k, v, v0, w, id;
2425
 
    Str tok, tmp, anchor;
2426
 
    table_attr align, valign;
2427
 
 
2428
 
    cmd = tag->tagid;
2429
 
 
2430
 
    if (mode->pre_mode & TBLM_PLAIN) {
2431
 
        if (mode->end_tag == cmd) {
2432
 
            mode->pre_mode &= ~TBLM_PLAIN;
2433
 
            mode->end_tag = 0;
2434
 
            feed_table_block_tag(tbl, line, mode, 0, cmd);
2435
 
            return TAG_ACTION_NONE;
2436
 
        }
2437
 
        return TAG_ACTION_PLAIN;
2438
 
    }
2439
 
    if (mode->pre_mode & TBLM_INTXTA) {
2440
 
        switch (cmd) {
2441
 
        CASE_TABLE_TAG:
2442
 
        case HTML_N_TEXTAREA:
2443
 
            table_close_textarea(tbl, mode, width);
2444
 
            if (cmd == HTML_N_TEXTAREA)
2445
 
                return TAG_ACTION_NONE;
2446
 
            break;
2447
 
        default:
2448
 
            return TAG_ACTION_FEED;
2449
 
        }
2450
 
    }
2451
 
    if (mode->pre_mode & TBLM_SCRIPT) {
2452
 
        if (mode->end_tag == cmd) {
2453
 
            mode->pre_mode &= ~TBLM_SCRIPT;
2454
 
            mode->end_tag = 0;
2455
 
            return TAG_ACTION_NONE;
2456
 
        }
2457
 
        return TAG_ACTION_PLAIN;
2458
 
    }
2459
 
    if (mode->pre_mode & TBLM_STYLE) {
2460
 
        if (mode->end_tag == cmd) {
2461
 
            mode->pre_mode &= ~TBLM_STYLE;
2462
 
            mode->end_tag = 0;
2463
 
            return TAG_ACTION_NONE;
2464
 
        }
2465
 
        return TAG_ACTION_PLAIN;
2466
 
    }
2467
 
    /* failsafe: a tag other than <option></option>and </select> in *
2468
 
     * <select> environment is regarded as the end of <select>. */
2469
 
    if (mode->pre_mode & TBLM_INSELECT) {
2470
 
        switch (cmd) {
2471
 
          CASE_TABLE_TAG:
2472
 
        case HTML_N_FORM:
2473
 
        case HTML_N_SELECT:     /* mode->end_tag */
2474
 
            table_close_select(tbl, mode, width);
2475
 
            if (cmd == HTML_N_SELECT)
2476
 
                return TAG_ACTION_NONE;
2477
 
            break;
2478
 
        default:
2479
 
            return TAG_ACTION_FEED;
2480
 
        }
2481
 
    }
2482
 
    if (mode->caption) {
2483
 
        switch (cmd) {
2484
 
          CASE_TABLE_TAG:
2485
 
        case HTML_N_CAPTION:
2486
 
            mode->caption = 0;
2487
 
            if (cmd == HTML_N_CAPTION)
2488
 
                return TAG_ACTION_NONE;
2489
 
            break;
2490
 
        default:
2491
 
            return TAG_ACTION_FEED;
2492
 
        }
2493
 
    }
2494
 
 
2495
 
    if (mode->pre_mode & TBLM_PRE) {
2496
 
        switch (cmd) {
2497
 
        case HTML_NOBR:
2498
 
        case HTML_N_NOBR:
2499
 
        case HTML_PRE_INT:
2500
 
        case HTML_N_PRE_INT:
2501
 
            return TAG_ACTION_NONE;
2502
 
        }
2503
 
    }
2504
 
 
2505
 
    switch (cmd) {
2506
 
    case HTML_TABLE:
2507
 
        check_rowcol(tbl, mode);
2508
 
        return TAG_ACTION_TABLE;
2509
 
    case HTML_N_TABLE:
2510
 
        if (tbl->suspended_data)
2511
 
            check_rowcol(tbl, mode);
2512
 
        return TAG_ACTION_N_TABLE;
2513
 
    case HTML_TR:
2514
 
        if (tbl->col >= 0 && tbl->tabcontentssize > 0)
2515
 
            setwidth(tbl, mode);
2516
 
        tbl->col = -1;
2517
 
        tbl->row++;
2518
 
        tbl->flag |= TBL_IN_ROW;
2519
 
        tbl->flag &= ~TBL_IN_COL;
2520
 
        align = 0;
2521
 
        valign = 0;
2522
 
        if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
2523
 
            switch (i) {
2524
 
            case ALIGN_LEFT:
2525
 
                align = (HTT_LEFT | HTT_TRSET);
2526
 
                break;
2527
 
            case ALIGN_RIGHT:
2528
 
                align = (HTT_RIGHT | HTT_TRSET);
2529
 
                break;
2530
 
            case ALIGN_CENTER:
2531
 
                align = (HTT_CENTER | HTT_TRSET);
2532
 
                break;
2533
 
            }
2534
 
        }
2535
 
        if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
2536
 
            switch (i) {
2537
 
            case VALIGN_TOP:
2538
 
                valign = (HTT_TOP | HTT_VTRSET);
2539
 
                break;
2540
 
            case VALIGN_MIDDLE:
2541
 
                valign = (HTT_MIDDLE | HTT_VTRSET);
2542
 
                break;
2543
 
            case VALIGN_BOTTOM:
2544
 
                valign = (HTT_BOTTOM | HTT_VTRSET);
2545
 
                break;
2546
 
            }
2547
 
        }
2548
 
#ifdef ID_EXT
2549
 
        if (parsedtag_get_value(tag, ATTR_ID, &p))
2550
 
            tbl->tridvalue[tbl->row] = Strnew_charp(p);
2551
 
#endif                          /* ID_EXT */
2552
 
        tbl->trattr = align | valign;
2553
 
        break;
2554
 
    case HTML_TH:
2555
 
    case HTML_TD:
2556
 
        prev_col = tbl->col;
2557
 
        if (tbl->col >= 0 && tbl->tabcontentssize > 0)
2558
 
            setwidth(tbl, mode);
2559
 
        if (tbl->row == -1) {
2560
 
            /* for broken HTML... */
2561
 
            tbl->row = -1;
2562
 
            tbl->col = -1;
2563
 
            tbl->maxrow = tbl->row;
2564
 
        }
2565
 
        if (tbl->col == -1) {
2566
 
            if (!(tbl->flag & TBL_IN_ROW)) {
2567
 
                tbl->row++;
2568
 
                tbl->flag |= TBL_IN_ROW;
2569
 
            }
2570
 
            if (tbl->row > tbl->maxrow)
2571
 
                tbl->maxrow = tbl->row;
2572
 
        }
2573
 
        tbl->col++;
2574
 
        check_row(tbl, tbl->row);
2575
 
        while (tbl->tabattr[tbl->row][tbl->col]) {
2576
 
            tbl->col++;
2577
 
        }
2578
 
        if (tbl->col > MAXCOL - 1) {
2579
 
            tbl->col = prev_col;
2580
 
            return TAG_ACTION_NONE;
2581
 
        }
2582
 
        if (tbl->col > tbl->maxcol) {
2583
 
            tbl->maxcol = tbl->col;
2584
 
        }
2585
 
        colspan = rowspan = 1;
2586
 
        if (tbl->trattr & HTT_TRSET)
2587
 
            align = (tbl->trattr & HTT_ALIGN);
2588
 
        else if (cmd == HTML_TH)
2589
 
            align = HTT_CENTER;
2590
 
        else
2591
 
            align = HTT_LEFT;
2592
 
        if (tbl->trattr & HTT_VTRSET)
2593
 
            valign = (tbl->trattr & HTT_VALIGN);
2594
 
        else
2595
 
            valign = HTT_MIDDLE;
2596
 
        if (parsedtag_get_value(tag, ATTR_ROWSPAN, &rowspan)) {
2597
 
            if(rowspan > ATTR_ROWSPAN_MAX) {
2598
 
                rowspan = ATTR_ROWSPAN_MAX;
2599
 
            }
2600
 
            if ((tbl->row + rowspan) >= tbl->max_rowsize)
2601
 
                check_row(tbl, tbl->row + rowspan);
2602
 
        }
2603
 
        if (parsedtag_get_value(tag, ATTR_COLSPAN, &colspan)) {
2604
 
            if ((tbl->col + colspan) >= MAXCOL) {
2605
 
                /* Can't expand column */
2606
 
                colspan = MAXCOL - tbl->col;
2607
 
            }
2608
 
        }
2609
 
        if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
2610
 
            switch (i) {
2611
 
            case ALIGN_LEFT:
2612
 
                align = HTT_LEFT;
2613
 
                break;
2614
 
            case ALIGN_RIGHT:
2615
 
                align = HTT_RIGHT;
2616
 
                break;
2617
 
            case ALIGN_CENTER:
2618
 
                align = HTT_CENTER;
2619
 
                break;
2620
 
            }
2621
 
        }
2622
 
        if (parsedtag_get_value(tag, ATTR_VALIGN, &i)) {
2623
 
            switch (i) {
2624
 
            case VALIGN_TOP:
2625
 
                valign = HTT_TOP;
2626
 
                break;
2627
 
            case VALIGN_MIDDLE:
2628
 
                valign = HTT_MIDDLE;
2629
 
                break;
2630
 
            case VALIGN_BOTTOM:
2631
 
                valign = HTT_BOTTOM;
2632
 
                break;
2633
 
            }
2634
 
        }
2635
 
#ifdef NOWRAP
2636
 
        if (parsedtag_exists(tag, ATTR_NOWRAP))
2637
 
            tbl->tabattr[tbl->row][tbl->col] |= HTT_NOWRAP;
2638
 
#endif                          /* NOWRAP */
2639
 
        v = 0;
2640
 
        if (parsedtag_get_value(tag, ATTR_WIDTH, &v)) {
2641
 
#ifdef TABLE_EXPAND
2642
 
            if (v > 0) {
2643
 
                if (tbl->real_width > 0)
2644
 
                    v = -(v * 100) / (tbl->real_width * pixel_per_char);
2645
 
                else
2646
 
                    v = (int)(v / pixel_per_char);
2647
 
            }
2648
 
#else
2649
 
            v = RELATIVE_WIDTH(v);
2650
 
#endif                          /* not TABLE_EXPAND */
2651
 
        }
2652
 
#ifdef ID_EXT
2653
 
        if (parsedtag_get_value(tag, ATTR_ID, &p))
2654
 
            tbl->tabidvalue[tbl->row][tbl->col] = Strnew_charp(p);
2655
 
#endif                          /* ID_EXT */
2656
 
#ifdef NOWRAP
2657
 
        if (v != 0) {
2658
 
            /* NOWRAP and WIDTH= conflicts each other */
2659
 
            tbl->tabattr[tbl->row][tbl->col] &= ~HTT_NOWRAP;
2660
 
        }
2661
 
#endif                          /* NOWRAP */
2662
 
        tbl->tabattr[tbl->row][tbl->col] &= ~(HTT_ALIGN | HTT_VALIGN);
2663
 
        tbl->tabattr[tbl->row][tbl->col] |= (align | valign);
2664
 
        if (colspan > 1) {
2665
 
            col = tbl->col;
2666
 
 
2667
 
            cell->icell = cell->maxcell + 1;
2668
 
            k = bsearch_2short(colspan, cell->colspan, col, cell->col, MAXCOL,
2669
 
                               cell->index, cell->icell);
2670
 
            if (k <= cell->maxcell) {
2671
 
                i = cell->index[k];
2672
 
                if (cell->col[i] == col && cell->colspan[i] == colspan)
2673
 
                    cell->icell = i;
2674
 
            }
2675
 
            if (cell->icell > cell->maxcell && cell->icell < MAXCELL) {
2676
 
                cell->maxcell++;
2677
 
                cell->col[cell->maxcell] = col;
2678
 
                cell->colspan[cell->maxcell] = colspan;
2679
 
                cell->width[cell->maxcell] = 0;
2680
 
                cell->minimum_width[cell->maxcell] = 0;
2681
 
                cell->fixed_width[cell->maxcell] = 0;
2682
 
                if (cell->maxcell > k) {
2683
 
                    int ii;
2684
 
                    for (ii = cell->maxcell; ii > k; ii--)
2685
 
                        cell->index[ii] = cell->index[ii - 1];
2686
 
                }
2687
 
                cell->index[k] = cell->maxcell;
2688
 
            }
2689
 
            if (cell->icell > cell->maxcell)
2690
 
                cell->icell = -1;
2691
 
        }
2692
 
        if (v != 0) {
2693
 
            if (colspan == 1) {
2694
 
                v0 = tbl->fixed_width[tbl->col];
2695
 
                if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0)) {
2696
 
#ifdef FEED_TABLE_DEBUG
2697
 
                    fprintf(stderr, "width(%d) = %d\n", tbl->col, v);
2698
 
#endif                          /* TABLE_DEBUG */
2699
 
                    tbl->fixed_width[tbl->col] = v;
2700
 
                }
2701
 
            }
2702
 
            else if (cell->icell >= 0) {
2703
 
                v0 = cell->fixed_width[cell->icell];
2704
 
                if (v0 == 0 || (v0 > 0 && v > v0) || (v0 < 0 && v < v0))
2705
 
                    cell->fixed_width[cell->icell] = v;
2706
 
            }
2707
 
        }
2708
 
        for (i = 0; i < rowspan; i++) {
2709
 
            check_row(tbl, tbl->row + i);
2710
 
            for (j = 0; j < colspan; j++) {
2711
 
#if 0
2712
 
                tbl->tabattr[tbl->row + i][tbl->col + j] &= ~(HTT_X | HTT_Y);
2713
 
#endif
2714
 
                if (!(tbl->tabattr[tbl->row + i][tbl->col + j] &
2715
 
                      (HTT_X | HTT_Y))) {
2716
 
                    tbl->tabattr[tbl->row + i][tbl->col + j] |=
2717
 
                        ((i > 0) ? HTT_Y : 0) | ((j > 0) ? HTT_X : 0);
2718
 
                }
2719
 
                if (tbl->col + j > tbl->maxcol) {
2720
 
                    tbl->maxcol = tbl->col + j;
2721
 
                }
2722
 
            }
2723
 
            if (tbl->row + i > tbl->maxrow) {
2724
 
                tbl->maxrow = tbl->row + i;
2725
 
            }
2726
 
        }
2727
 
        begin_cell(tbl, mode);
2728
 
        break;
2729
 
    case HTML_N_TR:
2730
 
        setwidth(tbl, mode);
2731
 
        tbl->col = -1;
2732
 
        tbl->flag &= ~(TBL_IN_ROW | TBL_IN_COL);
2733
 
        return TAG_ACTION_NONE;
2734
 
    case HTML_N_TH:
2735
 
    case HTML_N_TD:
2736
 
        setwidth(tbl, mode);
2737
 
        tbl->flag &= ~TBL_IN_COL;
2738
 
#ifdef FEED_TABLE_DEBUG
2739
 
        {
2740
 
            TextListItem *it;
2741
 
            int i = tbl->col, j = tbl->row;
2742
 
            fprintf(stderr, "(a) row,col: %d, %d\n", j, i);
2743
 
            if (tbl->tabdata[j] && tbl->tabdata[j][i]) {
2744
 
                for (it = ((TextList *)tbl->tabdata[j][i])->first;
2745
 
                     it; it = it->next)
2746
 
                    fprintf(stderr, "  [%s] \n", it->ptr);
2747
 
            }
2748
 
        }
2749
 
#endif
2750
 
        return TAG_ACTION_NONE;
2751
 
    case HTML_P:
2752
 
    case HTML_BR:
2753
 
    case HTML_CENTER:
2754
 
    case HTML_N_CENTER:
2755
 
    case HTML_DIV:
2756
 
    case HTML_N_DIV:
2757
 
        if (!(tbl->flag & TBL_IN_ROW))
2758
 
            break;
2759
 
    case HTML_DT:
2760
 
    case HTML_DD:
2761
 
    case HTML_H:
2762
 
    case HTML_N_H:
2763
 
    case HTML_LI:
2764
 
    case HTML_PRE:
2765
 
    case HTML_N_PRE:
2766
 
    case HTML_HR:
2767
 
    case HTML_LISTING:
2768
 
    case HTML_XMP:
2769
 
    case HTML_PLAINTEXT:
2770
 
    case HTML_PRE_PLAIN:
2771
 
    case HTML_N_PRE_PLAIN:
2772
 
        feed_table_block_tag(tbl, line, mode, 0, cmd);
2773
 
        switch (cmd) {
2774
 
        case HTML_PRE:
2775
 
        case HTML_PRE_PLAIN:
2776
 
            mode->pre_mode |= TBLM_PRE;
2777
 
            break;
2778
 
        case HTML_N_PRE:
2779
 
        case HTML_N_PRE_PLAIN:
2780
 
            mode->pre_mode &= ~TBLM_PRE;
2781
 
            break;
2782
 
        case HTML_LISTING:
2783
 
            mode->pre_mode |= TBLM_PLAIN;
2784
 
            mode->end_tag = HTML_N_LISTING;
2785
 
            break;
2786
 
        case HTML_XMP:
2787
 
            mode->pre_mode |= TBLM_PLAIN;
2788
 
            mode->end_tag = HTML_N_XMP;
2789
 
            break;
2790
 
        case HTML_PLAINTEXT:
2791
 
            mode->pre_mode |= TBLM_PLAIN;
2792
 
            mode->end_tag = MAX_HTMLTAG;
2793
 
            break;
2794
 
        }
2795
 
        break;
2796
 
    case HTML_DL:
2797
 
    case HTML_BLQ:
2798
 
    case HTML_OL:
2799
 
    case HTML_UL:
2800
 
        feed_table_block_tag(tbl, line, mode, 1, cmd);
2801
 
        break;
2802
 
    case HTML_N_DL:
2803
 
    case HTML_N_BLQ:
2804
 
    case HTML_N_OL:
2805
 
    case HTML_N_UL:
2806
 
        feed_table_block_tag(tbl, line, mode, -1, cmd);
2807
 
        break;
2808
 
    case HTML_NOBR:
2809
 
    case HTML_WBR:
2810
 
        if (!(tbl->flag & TBL_IN_ROW))
2811
 
            break;
2812
 
    case HTML_PRE_INT:
2813
 
        feed_table_inline_tag(tbl, line, mode, -1);
2814
 
        switch (cmd) {
2815
 
        case HTML_NOBR:
2816
 
            mode->nobr_level++;
2817
 
            if (mode->pre_mode & TBLM_NOBR)
2818
 
                return TAG_ACTION_NONE;
2819
 
            mode->pre_mode |= TBLM_NOBR;
2820
 
            break;
2821
 
        case HTML_PRE_INT:
2822
 
            if (mode->pre_mode & TBLM_PRE_INT)
2823
 
                return TAG_ACTION_NONE;
2824
 
            mode->pre_mode |= TBLM_PRE_INT;
2825
 
            tbl->linfo.prev_spaces = 0;
2826
 
            break;
2827
 
        }
2828
 
        mode->nobr_offset = -1;
2829
 
        if (tbl->linfo.length > 0) {
2830
 
            check_minimum0(tbl, tbl->linfo.length);
2831
 
            tbl->linfo.length = 0;
2832
 
        }
2833
 
        break;
2834
 
    case HTML_N_NOBR:
2835
 
        if (!(tbl->flag & TBL_IN_ROW))
2836
 
            break;
2837
 
        feed_table_inline_tag(tbl, line, mode, -1);
2838
 
        if (mode->nobr_level > 0)
2839
 
            mode->nobr_level--;
2840
 
        if (mode->nobr_level == 0)
2841
 
            mode->pre_mode &= ~TBLM_NOBR;
2842
 
        break;
2843
 
    case HTML_N_PRE_INT:
2844
 
        feed_table_inline_tag(tbl, line, mode, -1);
2845
 
        mode->pre_mode &= ~TBLM_PRE_INT;
2846
 
        break;
2847
 
    case HTML_IMG:
2848
 
        check_rowcol(tbl, mode);
2849
 
        w = tbl->fixed_width[tbl->col];
2850
 
        if (w < 0) {
2851
 
            if (tbl->total_width > 0)
2852
 
                w = -tbl->total_width * w / 100;
2853
 
            else if (width > 0)
2854
 
                w = -width * w / 100;
2855
 
            else
2856
 
                w = 0;
2857
 
        }
2858
 
        else if (w == 0) {
2859
 
            if (tbl->total_width > 0)
2860
 
                w = tbl->total_width;
2861
 
            else if (width > 0)
2862
 
                w = width;
2863
 
        }
2864
 
        tok = process_img(tag, w);
2865
 
        feed_table1(tbl, tok, mode, width);
2866
 
        break;
2867
 
    case HTML_FORM:
2868
 
        feed_table_block_tag(tbl, "", mode, 0, cmd);
2869
 
        tmp = process_form(tag);
2870
 
        if (tmp)
2871
 
            feed_table1(tbl, tmp, mode, width);
2872
 
        break;
2873
 
    case HTML_N_FORM:
2874
 
        feed_table_block_tag(tbl, "", mode, 0, cmd);
2875
 
        process_n_form();
2876
 
        break;
2877
 
    case HTML_INPUT:
2878
 
        tmp = process_input(tag);
2879
 
        feed_table1(tbl, tmp, mode, width);
2880
 
        break;
2881
 
    case HTML_SELECT:
2882
 
        tmp = process_select(tag);
2883
 
        if (tmp)
2884
 
            feed_table1(tbl, tmp, mode, width);
2885
 
        mode->pre_mode |= TBLM_INSELECT;
2886
 
        mode->end_tag = HTML_N_SELECT;
2887
 
        break;
2888
 
    case HTML_N_SELECT:
2889
 
    case HTML_OPTION:
2890
 
        /* nothing */
2891
 
        break;
2892
 
    case HTML_TEXTAREA:
2893
 
        w = 0;
2894
 
        check_rowcol(tbl, mode);
2895
 
        if (tbl->col + 1 <= tbl->maxcol &&
2896
 
            tbl->tabattr[tbl->row][tbl->col + 1] & HTT_X) {
2897
 
            if (cell->icell >= 0 && cell->fixed_width[cell->icell] > 0)
2898
 
                w = cell->fixed_width[cell->icell];
2899
 
        }
2900
 
        else {
2901
 
            if (tbl->fixed_width[tbl->col] > 0)
2902
 
                w = tbl->fixed_width[tbl->col];
2903
 
        }
2904
 
        tmp = process_textarea(tag, w);
2905
 
        if (tmp)
2906
 
            feed_table1(tbl, tmp, mode, width);
2907
 
        mode->pre_mode |= TBLM_INTXTA;
2908
 
        mode->end_tag = HTML_N_TEXTAREA;
2909
 
        break;
2910
 
    case HTML_A:
2911
 
        table_close_anchor0(tbl, mode);
2912
 
        anchor = NULL;
2913
 
        i = 0;
2914
 
        parsedtag_get_value(tag, ATTR_HREF, &anchor);
2915
 
        parsedtag_get_value(tag, ATTR_HSEQ, &i);
2916
 
        if (anchor) {
2917
 
            check_rowcol(tbl, mode);
2918
 
            if (i == 0) {
2919
 
                Str tmp = process_anchor(tag, line);
2920
 
                if (displayLinkNumber)
2921
 
                {
2922
 
                        Str t = getLinkNumberStr(-1);
2923
 
                        feed_table_inline_tag(tbl, NULL, mode, t->length);
2924
 
                        Strcat(tmp, t);
2925
 
                }
2926
 
                pushdata(tbl, tbl->row, tbl->col, tmp->ptr);
2927
 
            }
2928
 
            else
2929
 
                pushdata(tbl, tbl->row, tbl->col, line);
2930
 
            if (i >= 0) {
2931
 
                mode->pre_mode |= TBLM_ANCHOR;
2932
 
                mode->anchor_offset = tbl->tabcontentssize;
2933
 
            }
2934
 
        }
2935
 
        else
2936
 
            suspend_or_pushdata(tbl, line);
2937
 
        break;
2938
 
    case HTML_DEL:
2939
 
        switch (displayInsDel) {
2940
 
        case DISPLAY_INS_DEL_SIMPLE:
2941
 
            mode->pre_mode |= TBLM_DEL;
2942
 
            break;
2943
 
        case DISPLAY_INS_DEL_NORMAL:
2944
 
            feed_table_inline_tag(tbl, line, mode, 5);  /* [DEL: */
2945
 
            break;
2946
 
        case DISPLAY_INS_DEL_FONTIFY:
2947
 
            feed_table_inline_tag(tbl, line, mode, -1);
2948
 
            break;
2949
 
        }
2950
 
        break;
2951
 
    case HTML_N_DEL:
2952
 
        switch (displayInsDel) {
2953
 
        case DISPLAY_INS_DEL_SIMPLE:
2954
 
            mode->pre_mode &= ~TBLM_DEL;
2955
 
            break;
2956
 
        case DISPLAY_INS_DEL_NORMAL:
2957
 
            feed_table_inline_tag(tbl, line, mode, 5);  /* :DEL] */
2958
 
            break;
2959
 
        case DISPLAY_INS_DEL_FONTIFY:
2960
 
            feed_table_inline_tag(tbl, line, mode, -1);
2961
 
            break;
2962
 
        }
2963
 
        break;
2964
 
    case HTML_S:
2965
 
        switch (displayInsDel) {
2966
 
        case DISPLAY_INS_DEL_SIMPLE:
2967
 
            mode->pre_mode |= TBLM_S;
2968
 
            break;
2969
 
        case DISPLAY_INS_DEL_NORMAL:
2970
 
            feed_table_inline_tag(tbl, line, mode, 3);  /* [S: */
2971
 
            break;
2972
 
        case DISPLAY_INS_DEL_FONTIFY:
2973
 
            feed_table_inline_tag(tbl, line, mode, -1);
2974
 
            break;
2975
 
        }
2976
 
        break;
2977
 
    case HTML_N_S:
2978
 
        switch (displayInsDel) {
2979
 
        case DISPLAY_INS_DEL_SIMPLE:
2980
 
            mode->pre_mode &= ~TBLM_S;
2981
 
            break;
2982
 
        case DISPLAY_INS_DEL_NORMAL:
2983
 
            feed_table_inline_tag(tbl, line, mode, 3);  /* :S] */
2984
 
            break;
2985
 
        case DISPLAY_INS_DEL_FONTIFY:
2986
 
            feed_table_inline_tag(tbl, line, mode, -1);
2987
 
            break;
2988
 
        }
2989
 
        break;
2990
 
    case HTML_INS:
2991
 
    case HTML_N_INS:
2992
 
        switch (displayInsDel) {
2993
 
        case DISPLAY_INS_DEL_SIMPLE:
2994
 
            break;
2995
 
        case DISPLAY_INS_DEL_NORMAL:
2996
 
            feed_table_inline_tag(tbl, line, mode, 5);  /* [INS:, :INS] */
2997
 
            break;
2998
 
        case DISPLAY_INS_DEL_FONTIFY:
2999
 
            feed_table_inline_tag(tbl, line, mode, -1);
3000
 
            break;
3001
 
        }
3002
 
        break;
3003
 
    case HTML_SUP:
3004
 
    case HTML_SUB:
3005
 
    case HTML_N_SUB:
3006
 
        if (!(mode->pre_mode & (TBLM_DEL | TBLM_S)))
3007
 
            feed_table_inline_tag(tbl, line, mode, 1);  /* ^, [, ] */
3008
 
        break;
3009
 
    case HTML_N_SUP:
3010
 
        break;
3011
 
    case HTML_TABLE_ALT:
3012
 
        id = -1;
3013
 
        w = 0;
3014
 
        parsedtag_get_value(tag, ATTR_TID, &id);
3015
 
        if (id >= 0 && id < tbl->ntable) {
3016
 
            struct table *tbl1 = tbl->tables[id].ptr;
3017
 
            feed_table_block_tag(tbl, line, mode, 0, cmd);
3018
 
            addcontentssize(tbl, maximum_table_width(tbl1));
3019
 
            check_minimum0(tbl, tbl1->sloppy_width);
3020
 
#ifdef TABLE_EXPAND
3021
 
            w = tbl1->total_width;
3022
 
            v = 0;
3023
 
            colspan = table_colspan(tbl, tbl->row, tbl->col);
3024
 
            if (colspan > 1) {
3025
 
                if (cell->icell >= 0)
3026
 
                    v = cell->fixed_width[cell->icell];
3027
 
            }
3028
 
            else
3029
 
                v = tbl->fixed_width[tbl->col];
3030
 
            if (v < 0 && tbl->real_width > 0 && tbl1->real_width > 0)
3031
 
                w = -(tbl1->real_width * 100) / tbl->real_width;
3032
 
            else
3033
 
                w = tbl1->real_width;
3034
 
            if (w > 0)
3035
 
                check_minimum0(tbl, w);
3036
 
            else if (w < 0 && v < w) {
3037
 
                if (colspan > 1) {
3038
 
                    if (cell->icell >= 0)
3039
 
                        cell->fixed_width[cell->icell] = w;
3040
 
                }
3041
 
                else
3042
 
                    tbl->fixed_width[tbl->col] = w;
3043
 
            }
3044
 
#endif
3045
 
            setwidth0(tbl, mode);
3046
 
            clearcontentssize(tbl, mode);
3047
 
        }
3048
 
        break;
3049
 
    case HTML_CAPTION:
3050
 
        mode->caption = 1;
3051
 
        break;
3052
 
    case HTML_N_CAPTION:
3053
 
    case HTML_THEAD:
3054
 
    case HTML_N_THEAD:
3055
 
    case HTML_TBODY:
3056
 
    case HTML_N_TBODY:
3057
 
    case HTML_TFOOT:
3058
 
    case HTML_N_TFOOT:
3059
 
    case HTML_COLGROUP:
3060
 
    case HTML_N_COLGROUP:
3061
 
    case HTML_COL:
3062
 
        break;
3063
 
    case HTML_SCRIPT:
3064
 
        mode->pre_mode |= TBLM_SCRIPT;
3065
 
        mode->end_tag = HTML_N_SCRIPT;
3066
 
        break;
3067
 
    case HTML_STYLE:
3068
 
        mode->pre_mode |= TBLM_STYLE;
3069
 
        mode->end_tag = HTML_N_STYLE;
3070
 
        break;
3071
 
    case HTML_N_A:
3072
 
        table_close_anchor0(tbl, mode);
3073
 
    case HTML_FONT:
3074
 
    case HTML_N_FONT:
3075
 
    case HTML_NOP:
3076
 
        suspend_or_pushdata(tbl, line);
3077
 
        break;
3078
 
    case HTML_INTERNAL:
3079
 
    case HTML_N_INTERNAL:
3080
 
    case HTML_FORM_INT:
3081
 
    case HTML_N_FORM_INT:
3082
 
    case HTML_INPUT_ALT:
3083
 
    case HTML_N_INPUT_ALT:
3084
 
    case HTML_SELECT_INT:
3085
 
    case HTML_N_SELECT_INT:
3086
 
    case HTML_OPTION_INT:
3087
 
    case HTML_TEXTAREA_INT:
3088
 
    case HTML_N_TEXTAREA_INT:
3089
 
    case HTML_IMG_ALT:
3090
 
    case HTML_SYMBOL:
3091
 
    case HTML_N_SYMBOL:
3092
 
    default:
3093
 
        /* unknown tag: put into table */
3094
 
        return TAG_ACTION_FEED;
3095
 
    }
3096
 
    return TAG_ACTION_NONE;
3097
 
}
3098
 
 
3099
 
 
3100
 
int
3101
 
feed_table(struct table *tbl, char *line, struct table_mode *mode,
3102
 
           int width, int internal)
3103
 
{
3104
 
    int i;
3105
 
    char *p;
3106
 
    Str tmp;
3107
 
    struct table_linfo *linfo = &tbl->linfo;
3108
 
 
3109
 
    if (*line == '<' && line[1] && REALLY_THE_BEGINNING_OF_A_TAG(line)) {
3110
 
        struct parsed_tag *tag;
3111
 
        p = line;
3112
 
        tag = parse_tag(&p, internal);
3113
 
        if (tag) {
3114
 
            switch (feed_table_tag(tbl, line, mode, width, tag)) {
3115
 
            case TAG_ACTION_NONE:
3116
 
                return -1;
3117
 
            case TAG_ACTION_N_TABLE:
3118
 
                return 0;
3119
 
            case TAG_ACTION_TABLE:
3120
 
                return 1;
3121
 
            case TAG_ACTION_PLAIN:
3122
 
                break;
3123
 
            case TAG_ACTION_FEED:
3124
 
            default:
3125
 
                if (parsedtag_need_reconstruct(tag))
3126
 
                    line = parsedtag2str(tag)->ptr;
3127
 
            }
3128
 
        }
3129
 
        else {
3130
 
            if (!(mode->pre_mode & (TBLM_PLAIN | TBLM_INTXTA | TBLM_INSELECT |
3131
 
                                    TBLM_SCRIPT | TBLM_STYLE)))
3132
 
                return -1;
3133
 
        }
3134
 
    }
3135
 
    else {
3136
 
        if (mode->pre_mode & (TBLM_DEL | TBLM_S))
3137
 
            return -1;
3138
 
    }
3139
 
    if (mode->caption) {
3140
 
        Strcat_charp(tbl->caption, line);
3141
 
        return -1;
3142
 
    }
3143
 
    if (mode->pre_mode & TBLM_SCRIPT)
3144
 
        return -1;
3145
 
    if (mode->pre_mode & TBLM_STYLE)
3146
 
        return -1;
3147
 
    if (mode->pre_mode & TBLM_INTXTA) {
3148
 
        feed_textarea(line);
3149
 
        return -1;
3150
 
    }
3151
 
    if (mode->pre_mode & TBLM_INSELECT) {
3152
 
        feed_select(line);
3153
 
        return -1;
3154
 
    }
3155
 
    if (!(mode->pre_mode & TBLM_PLAIN) &&
3156
 
        !(*line == '<' && line[strlen(line) - 1] == '>') &&
3157
 
        strchr(line, '&') != NULL) {
3158
 
        tmp = Strnew();
3159
 
        for (p = line; *p;) {
3160
 
            char *q, *r;
3161
 
            if (*p == '&') {
3162
 
                if (!strncasecmp(p, "&amp;", 5) ||
3163
 
                    !strncasecmp(p, "&gt;", 4) || !strncasecmp(p, "&lt;", 4)) {
3164
 
                    /* do not convert */
3165
 
                    Strcat_char(tmp, *p);
3166
 
                    p++;
3167
 
                }
3168
 
                else {
3169
 
                    int ec;
3170
 
                    q = p;
3171
 
                    switch (ec = getescapechar(&p)) {
3172
 
                    case '<':
3173
 
                        Strcat_charp(tmp, "&lt;");
3174
 
                        break;
3175
 
                    case '>':
3176
 
                        Strcat_charp(tmp, "&gt;");
3177
 
                        break;
3178
 
                    case '&':
3179
 
                        Strcat_charp(tmp, "&amp;");
3180
 
                        break;
3181
 
                    case '\r':
3182
 
                        Strcat_char(tmp, '\n');
3183
 
                        break;
3184
 
                    default:
3185
 
                        r = conv_entity(ec);
3186
 
                        if (r != NULL && strlen(r) == 1 &&
3187
 
                            ec == (unsigned char)*r) {
3188
 
                            Strcat_char(tmp, *r);
3189
 
                            break;
3190
 
                        }
3191
 
                    case -1:
3192
 
                        Strcat_char(tmp, *q);
3193
 
                        p = q + 1;
3194
 
                        break;
3195
 
                    }
3196
 
                }
3197
 
            }
3198
 
            else {
3199
 
                Strcat_char(tmp, *p);
3200
 
                p++;
3201
 
            }
3202
 
        }
3203
 
        line = tmp->ptr;
3204
 
    }
3205
 
    if (!(mode->pre_mode & (TBLM_SPECIAL & ~TBLM_NOBR))) {
3206
 
        if (!(tbl->flag & TBL_IN_COL) || linfo->prev_spaces != 0)
3207
 
            while (IS_SPACE(*line))
3208
 
                line++;
3209
 
        if (*line == '\0')
3210
 
            return -1;
3211
 
        check_rowcol(tbl, mode);
3212
 
        if (mode->pre_mode & TBLM_NOBR && mode->nobr_offset < 0)
3213
 
            mode->nobr_offset = tbl->tabcontentssize;
3214
 
 
3215
 
        /* count of number of spaces skipped in normal mode */
3216
 
        i = skip_space(tbl, line, linfo, !(mode->pre_mode & TBLM_NOBR));
3217
 
        addcontentssize(tbl, visible_length(line) - i);
3218
 
        setwidth(tbl, mode);
3219
 
        pushdata(tbl, tbl->row, tbl->col, line);
3220
 
    }
3221
 
    else if (mode->pre_mode & TBLM_PRE_INT) {
3222
 
        check_rowcol(tbl, mode);
3223
 
        if (mode->nobr_offset < 0)
3224
 
            mode->nobr_offset = tbl->tabcontentssize;
3225
 
        addcontentssize(tbl, maximum_visible_length(line, tbl->tabcontentssize));
3226
 
        setwidth(tbl, mode);
3227
 
        pushdata(tbl, tbl->row, tbl->col, line);
3228
 
    }
3229
 
    else {
3230
 
        /* <pre> mode or something like it */
3231
 
        check_rowcol(tbl, mode);
3232
 
        while (*line) {
3233
 
            int nl = FALSE;
3234
 
            if ((p = strchr(line, '\r')) || (p = strchr(line, '\n'))) {
3235
 
                if (*p == '\r' && p[1] == '\n')
3236
 
                    p++;
3237
 
                if (p[1]) {
3238
 
                    p++;
3239
 
                    tmp = Strnew_charp_n(line, p - line);
3240
 
                    line = p;
3241
 
                    p = tmp->ptr;
3242
 
                }
3243
 
                else {
3244
 
                    p = line;
3245
 
                    line = "";
3246
 
                }
3247
 
                nl = TRUE;
3248
 
            }
3249
 
            else {
3250
 
                p = line;
3251
 
                line = "";
3252
 
            }
3253
 
            if (mode->pre_mode & TBLM_PLAIN)
3254
 
                i = maximum_visible_length_plain(p, tbl->tabcontentssize);
3255
 
            else
3256
 
                i = maximum_visible_length(p, tbl->tabcontentssize);
3257
 
            addcontentssize(tbl, i);
3258
 
            setwidth(tbl, mode);
3259
 
            if (nl)
3260
 
                clearcontentssize(tbl, mode);
3261
 
            pushdata(tbl, tbl->row, tbl->col, p);
3262
 
        }
3263
 
    }
3264
 
    return -1;
3265
 
}
3266
 
 
3267
 
void
3268
 
feed_table1(struct table *tbl, Str tok, struct table_mode *mode, int width)
3269
 
{
3270
 
    Str tokbuf;
3271
 
    int status;
3272
 
    char *line;
3273
 
    if (!tok)
3274
 
        return;
3275
 
    tokbuf = Strnew();
3276
 
    status = R_ST_NORMAL;
3277
 
    line = tok->ptr;
3278
 
    while (read_token
3279
 
           (tokbuf, &line, &status, mode->pre_mode & TBLM_PREMODE, 0))
3280
 
        feed_table(tbl, tokbuf->ptr, mode, width, TRUE);
3281
 
}
3282
 
 
3283
 
void
3284
 
pushTable(struct table *tbl, struct table *tbl1)
3285
 
{
3286
 
    int col;
3287
 
    int row;
3288
 
 
3289
 
    col = tbl->col;
3290
 
    row = tbl->row;
3291
 
 
3292
 
    if (tbl->ntable >= tbl->tables_size) {
3293
 
        struct table_in *tmp;
3294
 
        tbl->tables_size += MAX_TABLE_N;
3295
 
        tmp = New_N(struct table_in, tbl->tables_size);
3296
 
        if (tbl->tables)
3297
 
            bcopy(tbl->tables, tmp, tbl->ntable * sizeof(struct table_in));
3298
 
        tbl->tables = tmp;
3299
 
    }
3300
 
 
3301
 
    tbl->tables[tbl->ntable].ptr = tbl1;
3302
 
    tbl->tables[tbl->ntable].col = col;
3303
 
    tbl->tables[tbl->ntable].row = row;
3304
 
    tbl->tables[tbl->ntable].indent = tbl->indent;
3305
 
    tbl->tables[tbl->ntable].buf = newTextLineList();
3306
 
    check_row(tbl, row);
3307
 
    if (col + 1 <= tbl->maxcol && tbl->tabattr[row][col + 1] & HTT_X)
3308
 
        tbl->tables[tbl->ntable].cell = tbl->cell.icell;
3309
 
    else
3310
 
        tbl->tables[tbl->ntable].cell = -1;
3311
 
    tbl->ntable++;
3312
 
}
3313
 
 
3314
 
#ifdef MATRIX
3315
 
int
3316
 
correct_table_matrix(struct table *t, int col, int cspan, int a, double b)
3317
 
{
3318
 
    int i, j;
3319
 
    int ecol = col + cspan;
3320
 
    double w = 1. / (b * b);
3321
 
 
3322
 
    for (i = col; i < ecol; i++) {
3323
 
        v_add_val(t->vector, i, w * a);
3324
 
        for (j = i; j < ecol; j++) {
3325
 
            m_add_val(t->matrix, i, j, w);
3326
 
            m_set_val(t->matrix, j, i, m_entry(t->matrix, i, j));
3327
 
        }
3328
 
    }
3329
 
    return i;
3330
 
}
3331
 
 
3332
 
static void
3333
 
correct_table_matrix2(struct table *t, int col, int cspan, double s, double b)
3334
 
{
3335
 
    int i, j;
3336
 
    int ecol = col + cspan;
3337
 
    int size = t->maxcol + 1;
3338
 
    double w = 1. / (b * b);
3339
 
    double ss;
3340
 
 
3341
 
    for (i = 0; i < size; i++) {
3342
 
        for (j = i; j < size; j++) {
3343
 
            if (i >= col && i < ecol && j >= col && j < ecol)
3344
 
                ss = (1. - s) * (1. - s);
3345
 
            else if ((i >= col && i < ecol) || (j >= col && j < ecol))
3346
 
                ss = -(1. - s) * s;
3347
 
            else
3348
 
                ss = s * s;
3349
 
            m_add_val(t->matrix, i, j, w * ss);
3350
 
        }
3351
 
    }
3352
 
}
3353
 
 
3354
 
static void
3355
 
correct_table_matrix3(struct table *t, int col, char *flags, double s,
3356
 
                      double b)
3357
 
{
3358
 
    int i, j;
3359
 
    double ss;
3360
 
    int size = t->maxcol + 1;
3361
 
    double w = 1. / (b * b);
3362
 
    int flg = (flags[col] == 0);
3363
 
 
3364
 
    for (i = 0; i < size; i++) {
3365
 
        if (!((flg && flags[i] == 0) || (!flg && flags[i] != 0)))
3366
 
            continue;
3367
 
        for (j = i; j < size; j++) {
3368
 
            if (!((flg && flags[j] == 0) || (!flg && flags[j] != 0)))
3369
 
                continue;
3370
 
            if (i == col && j == col)
3371
 
                ss = (1. - s) * (1. - s);
3372
 
            else if (i == col || j == col)
3373
 
                ss = -(1. - s) * s;
3374
 
            else
3375
 
                ss = s * s;
3376
 
            m_add_val(t->matrix, i, j, w * ss);
3377
 
        }
3378
 
    }
3379
 
}
3380
 
 
3381
 
static void
3382
 
correct_table_matrix4(struct table *t, int col, int cspan, char *flags,
3383
 
                      double s, double b)
3384
 
{
3385
 
    int i, j;
3386
 
    double ss;
3387
 
    int ecol = col + cspan;
3388
 
    int size = t->maxcol + 1;
3389
 
    double w = 1. / (b * b);
3390
 
 
3391
 
    for (i = 0; i < size; i++) {
3392
 
        if (flags[i] && !(i >= col && i < ecol))
3393
 
            continue;
3394
 
        for (j = i; j < size; j++) {
3395
 
            if (flags[j] && !(j >= col && j < ecol))
3396
 
                continue;
3397
 
            if (i >= col && i < ecol && j >= col && j < ecol)
3398
 
                ss = (1. - s) * (1. - s);
3399
 
            else if ((i >= col && i < ecol) || (j >= col && j < ecol))
3400
 
                ss = -(1. - s) * s;
3401
 
            else
3402
 
                ss = s * s;
3403
 
            m_add_val(t->matrix, i, j, w * ss);
3404
 
        }
3405
 
    }
3406
 
}
3407
 
 
3408
 
static void
3409
 
set_table_matrix0(struct table *t, int maxwidth)
3410
 
{
3411
 
    int size = t->maxcol + 1;
3412
 
    int i, j, k, bcol, ecol;
3413
 
    int width;
3414
 
    double w0, w1, w, s, b;
3415
 
#ifdef __GNUC__
3416
 
    double we[size];
3417
 
    char expand[size];
3418
 
#else                           /* not __GNUC__ */
3419
 
    double we[MAXCOL];
3420
 
    char expand[MAXCOL];
3421
 
#endif                          /* not __GNUC__ */
3422
 
    struct table_cell *cell = &t->cell;
3423
 
 
3424
 
    w0 = 0.;
3425
 
    for (i = 0; i < size; i++) {
3426
 
        we[i] = weight(t->tabwidth[i]);
3427
 
        w0 += we[i];
3428
 
    }
3429
 
    if (w0 <= 0.)
3430
 
        w0 = 1.;
3431
 
 
3432
 
    if (cell->necell == 0) {
3433
 
        for (i = 0; i < size; i++) {
3434
 
            s = we[i] / w0;
3435
 
            b = sigma_td_nw((int)(s * maxwidth));
3436
 
            correct_table_matrix2(t, i, 1, s, b);
3437
 
        }
3438
 
        return;
3439
 
    }
3440
 
 
3441
 
    bzero(expand, size);
3442
 
 
3443
 
    for (k = 0; k < cell->necell; k++) {
3444
 
        j = cell->eindex[k];
3445
 
        bcol = cell->col[j];
3446
 
        ecol = bcol + cell->colspan[j];
3447
 
        width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
3448
 
        w1 = 0.;
3449
 
        for (i = bcol; i < ecol; i++) {
3450
 
            w1 += t->tabwidth[i] + 0.1;
3451
 
            expand[i]++;
3452
 
        }
3453
 
        for (i = bcol; i < ecol; i++) {
3454
 
            w = weight(width * (t->tabwidth[i] + 0.1) / w1);
3455
 
            if (w > we[i])
3456
 
                we[i] = w;
3457
 
        }
3458
 
    }
3459
 
 
3460
 
    w0 = 0.;
3461
 
    w1 = 0.;
3462
 
    for (i = 0; i < size; i++) {
3463
 
        w0 += we[i];
3464
 
        if (expand[i] == 0)
3465
 
            w1 += we[i];
3466
 
    }
3467
 
    if (w0 <= 0.)
3468
 
        w0 = 1.;
3469
 
 
3470
 
    for (k = 0; k < cell->necell; k++) {
3471
 
        j = cell->eindex[k];
3472
 
        bcol = cell->col[j];
3473
 
        width = cell->width[j] - (cell->colspan[j] - 1) * t->cellspacing;
3474
 
        w = weight(width);
3475
 
        s = w / (w1 + w);
3476
 
        b = sigma_td_nw((int)(s * maxwidth));
3477
 
        correct_table_matrix4(t, bcol, cell->colspan[j], expand, s, b);
3478
 
    }
3479
 
 
3480
 
    for (i = 0; i < size; i++) {
3481
 
        if (expand[i] == 0) {
3482
 
            s = we[i] / max(w1, 1.);
3483
 
            b = sigma_td_nw((int)(s * maxwidth));
3484
 
        }
3485
 
        else {
3486
 
            s = we[i] / max(w0 - w1, 1.);
3487
 
            b = sigma_td_nw(maxwidth);
3488
 
        }
3489
 
        correct_table_matrix3(t, i, expand, s, b);
3490
 
    }
3491
 
}
3492
 
 
3493
 
void
3494
 
check_relative_width(struct table *t, int maxwidth)
3495
 
{
3496
 
    int i;
3497
 
    double rel_total = 0;
3498
 
    int size = t->maxcol + 1;
3499
 
    double *rcolwidth = New_N(double, size);
3500
 
    struct table_cell *cell = &t->cell;
3501
 
    int n_leftcol = 0;
3502
 
 
3503
 
    for (i = 0; i < size; i++)
3504
 
        rcolwidth[i] = 0;
3505
 
 
3506
 
    for (i = 0; i < size; i++) {
3507
 
        if (t->fixed_width[i] < 0)
3508
 
            rcolwidth[i] = -(double)t->fixed_width[i] / 100.0;
3509
 
        else if (t->fixed_width[i] > 0)
3510
 
            rcolwidth[i] = (double)t->fixed_width[i] / maxwidth;
3511
 
        else
3512
 
            n_leftcol++;
3513
 
    }
3514
 
    for (i = 0; i <= cell->maxcell; i++) {
3515
 
        if (cell->fixed_width[i] < 0) {
3516
 
            double w = -(double)cell->fixed_width[i] / 100.0;
3517
 
            double r;
3518
 
            int j, k;
3519
 
            int n_leftcell = 0;
3520
 
            k = cell->col[i];
3521
 
            r = 0.0;
3522
 
            for (j = 0; j < cell->colspan[i]; j++) {
3523
 
                if (rcolwidth[j + k] > 0)
3524
 
                    r += rcolwidth[j + k];
3525
 
                else
3526
 
                    n_leftcell++;
3527
 
            }
3528
 
            if (n_leftcell == 0) {
3529
 
                /* w must be identical to r */
3530
 
                if (w != r)
3531
 
                    cell->fixed_width[i] = -100 * r;
3532
 
            }
3533
 
            else {
3534
 
                if (w <= r) {
3535
 
                    /* make room for the left(width-unspecified) cell */
3536
 
                    /* the next formula is an estimation of required width */
3537
 
                    w = r * cell->colspan[i] / (cell->colspan[i] - n_leftcell);
3538
 
                    cell->fixed_width[i] = -100 * w;
3539
 
                }
3540
 
                for (j = 0; j < cell->colspan[i]; j++) {
3541
 
                    if (rcolwidth[j + k] == 0)
3542
 
                        rcolwidth[j + k] = (w - r) / n_leftcell;
3543
 
                }
3544
 
            }
3545
 
        }
3546
 
        else if (cell->fixed_width[i] > 0) {
3547
 
            /* todo */
3548
 
        }
3549
 
    }
3550
 
    /* sanity check */
3551
 
    for (i = 0; i < size; i++)
3552
 
        rel_total += rcolwidth[i];
3553
 
 
3554
 
    if ((n_leftcol == 0 && rel_total < 0.9) || 1.1 < rel_total) {
3555
 
        for (i = 0; i < size; i++) {
3556
 
            rcolwidth[i] /= rel_total;
3557
 
        }
3558
 
        for (i = 0; i < size; i++) {
3559
 
            if (t->fixed_width[i] < 0)
3560
 
                t->fixed_width[i] = -rcolwidth[i] * 100;
3561
 
        }
3562
 
        for (i = 0; i <= cell->maxcell; i++) {
3563
 
            if (cell->fixed_width[i] < 0) {
3564
 
                double r;
3565
 
                int j, k;
3566
 
                k = cell->col[i];
3567
 
                r = 0.0;
3568
 
                for (j = 0; j < cell->colspan[i]; j++)
3569
 
                    r += rcolwidth[j + k];
3570
 
                cell->fixed_width[i] = -r * 100;
3571
 
            }
3572
 
        }
3573
 
    }
3574
 
}
3575
 
 
3576
 
void
3577
 
set_table_matrix(struct table *t, int width)
3578
 
{
3579
 
    int size = t->maxcol + 1;
3580
 
    int i, j;
3581
 
    double b, s;
3582
 
    int a;
3583
 
    struct table_cell *cell = &t->cell;
3584
 
 
3585
 
    if (size < 1)
3586
 
        return;
3587
 
 
3588
 
    t->matrix = m_get(size, size);
3589
 
    t->vector = v_get(size);
3590
 
    for (i = 0; i < size; i++) {
3591
 
        for (j = i; j < size; j++)
3592
 
            m_set_val(t->matrix, i, j, 0.);
3593
 
        v_set_val(t->vector, i, 0.);
3594
 
    }
3595
 
 
3596
 
    check_relative_width(t, width);
3597
 
 
3598
 
    for (i = 0; i < size; i++) {
3599
 
        if (t->fixed_width[i] > 0) {
3600
 
            a = max(t->fixed_width[i], t->minimum_width[i]);
3601
 
            b = sigma_td(a);
3602
 
            correct_table_matrix(t, i, 1, a, b);
3603
 
        }
3604
 
        else if (t->fixed_width[i] < 0) {
3605
 
            s = -(double)t->fixed_width[i] / 100.;
3606
 
            b = sigma_td((int)(s * width));
3607
 
            correct_table_matrix2(t, i, 1, s, b);
3608
 
        }
3609
 
    }
3610
 
 
3611
 
    for (j = 0; j <= cell->maxcell; j++) {
3612
 
        if (cell->fixed_width[j] > 0) {
3613
 
            a = max(cell->fixed_width[j], cell->minimum_width[j]);
3614
 
            b = sigma_td(a);
3615
 
            correct_table_matrix(t, cell->col[j], cell->colspan[j], a, b);
3616
 
        }
3617
 
        else if (cell->fixed_width[j] < 0) {
3618
 
            s = -(double)cell->fixed_width[j] / 100.;
3619
 
            b = sigma_td((int)(s * width));
3620
 
            correct_table_matrix2(t, cell->col[j], cell->colspan[j], s, b);
3621
 
        }
3622
 
    }
3623
 
 
3624
 
    set_table_matrix0(t, width);
3625
 
 
3626
 
    if (t->total_width > 0) {
3627
 
        b = sigma_table(width);
3628
 
    }
3629
 
    else {
3630
 
        b = sigma_table_nw(width);
3631
 
    }
3632
 
    correct_table_matrix(t, 0, size, width, b);
3633
 
}
3634
 
#endif                          /* MATRIX */
3635
 
 
3636
 
/* Local Variables:    */
3637
 
/* c-basic-offset: 4   */
3638
 
/* tab-width: 8        */
3639
 
/* End:                */