39#define DFLT_CELLSPACING_3D 5
40#define DFLT_CELLSPACING_FLAT 0
41#define DFLT_CELLPADDING 2
46#define SETMAX(A,B) if ((A) < (B)) { (A) = (B); }
47#define MAX(A,B) ((A) < (B) ? (B) : (A))
68 cellSpacing = atoi(z);
80 int nw = 0, nh = 1, mw = 0;
134 if (!pTable->
fPEnd) {
152 while (p && (p = p->
fPNext)) {
176 if (cols > numcols) numcols = cols;
203 if ((!(cp = p->
MarkupArg(
"colspan", 0))) || (cspans = atoi(cp)) <= 0) {
206 if ((cp = p->
MarkupArg(
"rowspan", 0)) && (j = atoi(cp)) > 0 &&
215 while ((cspans - j) > 0) {
237 while ((cspans - j) > 0) {
242 if (
h > maxh) maxh =
h;
244 if (w > maxw[cols-1]) {
260 for (j = 0; j < p->
fCount; j++) {
279 snprintf(buf,
sizeof(buf),
"%d %d %d %d ", rows-1, cols-1,
286 while (nest--) str->
Append(
"} ");
289 snprintf(buf,
sizeof(buf),
"%d ", maxw[j]);
326 if (p == lp)
return 0;
333 }
else if (p->
fType ==
n) {
339 }
else if (p->
fType == en) {
340 if (!lvl--)
return p;
383 int minW, maxW, requestedW;
409# define ColMin(A,B) colMin[(A)-1][(B)-1]
410# define ColReq(A,B) colMin[(B)-1][(A)-1]
424 if (z && *z == 0) z =
"2";
449 separation = cellSpacing + 2 * (cellPadding + cbw);
450 margin = tbw + cellSpacing + cbw + cellPadding;
459 if (len > 0 && z[len-1] ==
'%') {
460 maxTableWidth = (atoi(z) * lineWidth) / 100;
462 maxTableWidth = atoi(z);
465 maxTableWidth = lineWidth;
467 maxTableWidth -= 2 * margin;
471 lineWidth, maxTableWidth, margin));
473 for (p = pStart->
fPNext; p; p = fPNext) {
501 availWidth = maxTableWidth;
516 if (pNew == 0)
break;
529 }
while (iCol1 <= pStart->fNCol && fromAbove[iCol1] > iRow);
533 if (colspan == 0) colspan = 1;
534 if (iCol1 + colspan - 1 > pStart->
fNCol) {
535 int nCol = iCol1 + colspan - 1;
537 for (i = pStart->
fNCol + 1; i <= nCol; i++) {
539 pStart->
fMinW[i] = 0;
540 pStart->
fMaxW[i] = 0;
544 for (j = 1; j < i; j++) {
549 pStart->
fNCol = nCol;
551 noWrap = (p->
MarkupArg(
"nowrap", 0) != 0);
554 fPNext =
MinMax(p, &minW, &maxW, availWidth, hasbg);
555 cell->
fPEnd = fPNext;
557 if ((z = p->
MarkupArg(
"width", 0)) != 0) {
558 for (i = 0; isdigit(z[i]) || z[i] ==
'.'; i++) {}
559 if (strcmp(z,
"*") == 0) {
560 requestedW = availWidth;
561 }
else if (z[i] == 0) {
562 requestedW = atoi(z);
563 }
else if (z[i] ==
'%') {
564 requestedW = (atoi(z) * maxTableWidth + 99) / 100;
569 (
"Row %d Column %d: min=%d max=%d req=%d stop at %s\n",
570 iRow, iCol1, minW, maxW, requestedW,
584 SETMAX(min0span[iCol1], minW);
585 SETMAX(max0span[iCol1], maxW);
586 min = min0span[iCol1] + separation;
587 }
else if (colspan == 1) {
590 SETMAX(reqW[iCol1], requestedW);
591 min = pStart->
fMinW[iCol1] + separation;
598 min = minW + separation;
599 for (ix = iCol1; ix < iCol1 + n2; ix++) {
611 fromAbove[i] = iRow + rowspan;
626 const char *zSpace =
"";
628 for (i = 1; i <= pStart->
fNCol; i++) {
629 printf(
"%s%d:%d..%d", zSpace, i, pStart->
fMinW[i], pStart->
fMaxW[i]);
631 printf(
"(w=%d)", reqW[i]);
636 for (i = 1; i < pStart->
fNCol; i++) {
637 for (j = i+1; j <= pStart->
fNCol; j++) {
640 printf(
"ColMin(%d,%d) = %d\n", i, j,
ColMin(i, j));
644 printf(
"ColReq(%d,%d) = %d\n", i, j,
ColReq(i, j));
653 for (i = 1; i <= pStart->
fNCol; i++) {
654 int sumMin, sumReq, sumMax;
663 if (min0span[i] > 0 || max0span[i] > 0) {
664 int n2 = pStart->
fNCol - i + 1;
665 minW = (min0span[i] + (n2 - 1) * (1 - separation)) / n2;
666 maxW = (max0span[i] + (n2 - 1) * (1 - separation)) / n2;
667 for (j = i; j <= pStart->
fNCol; j++) {
679 sumMin = pStart->
fMinW[i];
680 sumMax = pStart->
fMaxW[i];
681 for (j = i-1; j >= 1; j--) {
684 sumMin += pStart->
fMinW[j];
685 sumMax += pStart->
fMaxW[j];
693 int *tminW = pStart->
fMinW;
694 int *tmaxW = pStart->
fMaxW;
695 if (sumMin < sumMax) {
696 scale = (
double) (cmin - sumMin) / (
double) (sumMax - sumMin);
697 for (k = j; k <= i; k++) {
699 tminW[k] = (
int) ((tmaxW[k] - tminW[k]) * scale + tminW[k]);
702 }
else if (sumMin > 0) {
703 scale = (
double) cmin / (
double) sumMin;
704 for (k = j; k <= i; k++) {
706 tminW[k] = tmaxW[k] = (
int) (tminW[k] * scale);
710 int unit = cmin / (i - j + 1);
711 for (k = j; k <= i; k++) {
712 tminW[k] = tmaxW[k] = unit;
723 int *tmaxW = pStart->
fMaxW;
724 if (sumReq < sumMax) {
725 scale = (
double) (creq - sumReq) / (
double) (sumMax - sumReq);
726 for (k = j; k <= i; k++) {
728 reqW[k] = (
int) ((tmaxW[k] - reqW[k]) * scale + reqW[k]);
731 }
else if (sumReq > 0) {
732 scale = (
double) creq / (
double) sumReq;
733 for (k = j; k <= i; k++) {
735 reqW[k] = (
int) (reqW[k] * scale);
739 int unit = creq / (i - j + 1);
740 for (k = j; k <= i; k++) {
751 const char *zSpace =
"";
753 for (i = 1; i <= pStart->
fNCol; i++) {
754 printf(
"%s%d:%d..%d", zSpace, i, pStart->
fMinW[i], pStart->
fMaxW[i]);
756 printf(
"(w=%d)", reqW[i]);
767 requestedW = tbw * 2 + (
n + 1) * cellSpacing +
n * 2 * (cellPadding + cbw);
768 pStart->
fMinW[0] = requestedW;
769 pStart->
fMaxW[0] = requestedW;
770 for (i = 1; i <= pStart->
fNCol; i++) {
773 requestedW +=
MAX(reqW[i], pStart->
fMinW[i]);
781 if (len > 0 && z[len-1] ==
'%') {
782 totalWidth = (atoi(z) * lineWidth) / 100;
784 totalWidth = atoi(z);
788 requestedW = totalWidth;
790 SETMAX(requestedW, totalWidth);
794 if (lineWidth && (requestedW > lineWidth)) {
797 requestedW, lineWidth));
799 requestedW = lineWidth;
801 if (requestedW > pStart->
fMinW[0]) {
803 int *tminW = pStart->
fMinW;
804 int *tmaxW = pStart->
fMaxW;
807 (
"Expanding table minW from %d to %d. (reqW=%d width=%s)\n",
808 tminW[0], requestedW, requestedW, z));
810 if (tmaxW[0] > tminW[0]) {
811 scale = (
double) (requestedW - tminW[0]) / (
double) (tmaxW[0] - tminW[0]);
812 for (i = 1; i <= pStart->
fNCol; i++) {
813 tminW[i] += (
int) ((tmaxW[i] - tminW[i]) * scale);
814 SETMAX(tmaxW[i], tminW[i]);
816 }
else if (tminW[0] > 0) {
817 scale = requestedW / (
double) tminW[0];
818 for (i = 1; i <= pStart->
fNCol; i++) {
819 tminW[i] = (
int) (tminW[i] * scale);
820 tmaxW[i] = (
int) (tmaxW[i] * scale);
822 }
else if (pStart->
fNCol > 0) {
823 int unit = (requestedW - margin) / pStart->
fNCol - separation;
824 if (unit < 0) unit = 0;
825 for (i = 1; i <= pStart->
fNCol; i++) {
826 tminW[i] = tmaxW[i] = unit;
829 tminW[0] = tmaxW[0] = requestedW;
831 pStart->
fMinW[0] = requestedW;
841 printf(
"nCol=%d minWidth=%d maxWidth=%d\n",
843 for (i = 1; i <= pStart->
fNCol; i++) {
845 printf(
"Column %d minWidth=%d maxWidth=%d\n",
852 (
"Result of TableDimensions: min=%d max=%d nCol=%d\n",
897 for (p = p->
fPNext; go && p; p = fPNext) {
949 obstacle += image->
fW;
1081#define VAlign_Unknown 0
1083#define VAlign_Bottom 2
1084#define VAlign_Center 3
1085#define VAlign_Baseline 4
1099 }
else if (strcasecmp(z,
"top") == 0) {
1101 }
else if (strcasecmp(z,
"bottom") == 0) {
1103 }
else if (strcasecmp(z,
"center") == 0) {
1105 }
else if (strcasecmp(z,
"baseline") == 0) {
1147#define N (HTML_MAX_COLUMNS+1)
1158#ifdef TABLE_TRIM_BLANK
1159 extern int HtmlLineWasBlank;
1168 for (i=0;i<
N;i++)
ymax[i]=0;
1178 btm, left_margin, lineWidth));
1188 if (lineWidth < pTable->fMinW[0]) {
1192 btm, left_margin, lineWidth));
1194 savedContext = *
this;
1199 int len = strlen(z);
1200 if (len > 0 && z[len-1] ==
'%') {
1201 specWidth = (atoi(z) * lineWidth) / 100;
1203 specWidth = atoi(z);
1206 specWidth = lineWidth;
1208 if (specWidth < pTable->fMinW[0]) {
1210 }
else if (specWidth <= pTable->fMaxW[0]) {
1219 z = pTable->
MarkupArg(
"cellpadding", 0);
1233 if (vspace < 2) vspace = 2;
1240 pad = cellPadding + cbw;
1241 separation = cellSpacing + 2 * pad;
1242 x[1] = left_margin + tbw + cellSpacing + pad;
1245 if (n <= 0 || pTable->fMaxW[0] <= 0) {
1251 zAlign = pTable->
MarkupArg(
"align",
"");
1252 if (
width <= lineWidth) {
1254 if (align ==
ALIGN_Right || strcasecmp(zAlign,
"right") == 0) {
1255 x[1] += lineWidth -
width;
1256 }
else if (align ==
ALIGN_Center && strcasecmp(zAlign,
"left") != 0) {
1257 x[1] += (lineWidth -
width) / 2;
1262 w[1] = pTable->
fMaxW[1];
1263 for (i = 2; i <=
n; i++) {
1264 w[i] = pTable->
fMaxW[i];
1265 x[i] =
x[i-1] + w[i-1] + separation;
1268 int *tmaxW = pTable->
fMaxW;
1270 w[1] = (
int) (tmaxW[1] * scale);
1271 for (i = 2; i <=
n; i++) {
1272 w[i] = (
int) (tmaxW[i] * scale);
1273 x[i] =
x[i-1] + w[i-1] + separation;
1277 int *tminW = pTable->
fMinW;
1278 int *tmaxW = pTable->
fMaxW;
1280 w[1] = (
int) (tminW[1] + (tmaxW[1] - tminW[1]) * scale);
1281 for (i = 2; i <=
n; i++) {
1282 w[i] = (
int) (tminW[i] + (tmaxW[i] - tminW[i]) * scale);
1283 x[i] =
x[i-1] + w[i-1] + separation;
1286 w[1] = pTable->
fMinW[1];
1287 for (i = 2; i <=
n; i++) {
1288 w[i] = pTable->
fMinW[i];
1289 x[i] =
x[i-1] + w[i-1] + separation;
1292 w[
n] =
width - ((
x[
n] -
x[1]) + 2 * (tbw + pad + cellSpacing));
1299 pTable->
fX =
x[1] - (tbw + cellSpacing + pad);
1302 btm += tbw + cellSpacing;
1305 for (i = 1; i <=
n; i++) {
1312 for (iRow = 1; iRow <= pTable->
fNRow; iRow++) {
1336 if (lastRow[iCol] < iRow)
ymax[iCol] = 0;
1354 (
"Column %d: x=%d w=%d\n",iCol,
x[iCol],w[iCol]));
1361 fPNext = cell->
fPEnd;
1363 lastRow[iCol] = pTable->
fNRow;
1365 lastRow[iCol] = iRow + cell->
fRowspan - 1;
1373 y[iCol] = btm + pad;
1376 cellContext.
fPEnd = fPNext;
1378 cellContext.
fTop =
y[iCol];
1380 cellContext.
fLeft =
x[iCol];
1388 lastRow[i] = lastRow[iCol];
1390 }
else if (colspan > 1) {
1394 lastRow[i] = lastRow[iCol];
1397 cellContext.
fMaxX = 0;
1398 cellContext.
fMaxY = 0;
1402#ifdef TABLE_TRIM_BLANK
1405 if (HtmlLineWasBlank) {
1406 cellContext.
fMaxY -= cellContext.headRoom;
1415 cell->
fX =
x[iCol] - pad;
1420 (
"Column %d top=%d bottom=%d h=%d left=%d w=%d\n",
1421 iCol,
y[iCol],
ymax[iCol],
ymax[iCol]-
y[iCol],
1422 cell->
fX, cell->
fW));
1426 iCol += colspan - 1;
1427 }
else if (colspan == 0) {
1446 for (iCol = 1; iCol <= pTable->
fNCol; iCol++) {
1447 if (lastRow[iCol] == iRow || iRow == pTable->
fNRow) {
1453 btm,rowBottom,rowBottom-btm));
1456 for (iCol = 1; iCol <= pTable->
fNCol; iCol++) {
1462 if (apElem[iCol] == 0 ||
1463 (iRow != pTable->
fNRow && lastRow[iCol] > iRow))
continue;
1466 switch (valign[iCol]) {
1469 dy = (rowBottom -
ymax[iCol])/2;
1476 dy = rowBottom -
ymax[iCol];
1488 apCell->
fH = rowBottom + pad - apCell->
fY;
1493 btm = rowBottom + pad + cellSpacing;
1497 pTable->
fH = btm - pTable->
fY;
1512 if (strcasecmp(zAlign,
"left") == 0) {
1515 *
this = savedContext;
1517 }
else if (strcasecmp(zAlign,
"right") == 0) {
1520 *
this = savedContext;
1527 "Done with TableLayout(). x=%d y=%d w=%d h=%d Return %s\n",
1528 pTable->
fX, pTable->
fY, pTable->
fW, pTable->
fH,
1544 if (dy == 0)
return;
1546 while (p && p != pLast1) {
static const double x2[5]
static const double x1[5]
static const double x3[11]
static void indent(ostringstream &buf, int indent_level)
include TDocParser_001 C image html pict1_TDocParser_001 png width
#define DFLT_CELLSPACING_FLAT
#define DFLT_CELLSPACING_3D
#define HTML_RELIEF_SUNKEN
#define HTML_RELIEF_RAISED
#define IMAGE_ALIGN_Right
#define TRACE(Flag, Args)
virtual int GetVerticalAlignment(int dflt)
virtual const char * MarkupArg(const char *, const char *)
void ComputeMargins(int *pX, int *pY, int *pW)
Compute the current margins for layout.
TGHtmlElement * TableLayout(TGHtmlTable *p)
Do all layout for a single table.
void LayoutBlock()
Do as much layout as possible on the block of text defined by the HtmlLayoutContext.
SHtmlMargin_t * fRightMargin
void PushMargin(SHtmlMargin_t **ppMargin, int indent, int bottom, int tag)
Push a new margin onto the given margin stack.
void ClearMarginStack(SHtmlMargin_t **ppMargin)
Clear a margin stack to reclaim memory.
void WidenLine(int reqWidth, int *pX, int *pY, int *pW)
Move past obstacles until a linewidth of reqWidth is obtained, or until all obstacles are cleared.
SHtmlMargin_t * fLeftMargin
virtual int GetVerticalAlignment(int dflt)
Return the vertical alignment specified by the given element.
virtual const char * MarkupArg(const char *tag, const char *zDefault)
Lookup an argument in the given markup with the name given.
int fMinW[HTML_MAX_COLUMNS+1]
int fMaxW[HTML_MAX_COLUMNS+1]
void MoveVertically(TGHtmlElement *p, TGHtmlElement *pLast, int dy)
Move all elements in the given list vertically by the amount dy.
TGHtmlElement * MinMax(TGHtmlElement *p, int *pMin, int *pMax, int lineWidth, int hasbg)
Given a list of elements, compute the minimum and maximum width needed to render the list.
void StringHW(const char *str, int *h, int *w)
Return the height and width of string.
int CellSpacing(TGHtmlElement *pTable)
Return the appropriate cell spacing for the given table.
void AppendArglist(TGString *str, TGHtmlMarkupElement *pElem)
Append all the arguments of the given markup to the given TGString.
TGString * TableText(TGHtmlTable *pTable, int flags)
Return text and images from a table as lists.
TGHtmlElement * FindEndNest(TGHtmlElement *sp, int en, TGHtmlElement *lp)
Find End tag en, but ignore intervening begin/end tag pairs.
char * GetTokenName(TGHtmlElement *p)
Returns token name of html element p.
TGHtmlElement * TableDimensions(TGHtmlTable *pStart, int lineWidth)
pStart points to a
TGString wraps a TString and adds some graphics routines like drawing, size of string on screen depen...
const char * GetString() const
const char * Data() const
TString & Append(const char *cs)