00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <ctype.h>
00031 #include <math.h>
00032
00033 #include "TGHtml.h"
00034
00035
00036
00037
00038 #define DFLT_BORDER 0
00039 #define DFLT_CELLSPACING_3D 5
00040 #define DFLT_CELLSPACING_FLAT 0
00041 #define DFLT_CELLPADDING 2
00042 #define DFLT_HSPACE 0
00043 #define DFLT_VSPACE 0
00044
00045
00046 #define SETMAX(A,B) if ((A) < (B)) { (A) = (B); }
00047 #define MAX(A,B) ((A) < (B) ? (B) : (A))
00048
00049
00050
00051 int TGHtml::CellSpacing(TGHtmlElement *pTable)
00052 {
00053
00054
00055 const char *z;
00056 int relief;
00057 int cellSpacing;
00058
00059 z = pTable->MarkupArg("cellspacing", 0);
00060 if (z == 0) {
00061 relief = fTableRelief;
00062 if (relief == HTML_RELIEF_RAISED || relief == HTML_RELIEF_SUNKEN) {
00063 cellSpacing = DFLT_CELLSPACING_3D;
00064 } else {
00065 cellSpacing = DFLT_CELLSPACING_FLAT;
00066 }
00067 } else {
00068 cellSpacing = atoi(z);
00069 }
00070
00071 return cellSpacing;
00072 }
00073
00074
00075 void TGHtml::StringHW(const char *str, int *h, int *w)
00076 {
00077
00078
00079 const char *cp = str;
00080 int nw = 0, nh = 1, mw = 0;
00081 *h = 0; *w =0;
00082
00083 if (!cp) return;
00084
00085 while (*cp) {
00086 if (*cp != '\n') {
00087 nw++;
00088 } else {
00089 if (nw > mw) mw = nw;
00090 nw = 0;
00091 nh++;
00092 }
00093 cp++;
00094 }
00095 if (nw > mw) mw = nw;
00096 *w = mw;
00097 *h = nh;
00098 }
00099
00100
00101 TGString *TGHtml::TableText(TGHtmlTable *pTable, int flag)
00102 {
00103
00104
00105
00106
00107
00108
00109
00110 int j, h, w,
00111 nest = 0,
00112
00113 rows = 0,
00114 cols = 0,
00115 numcols = 0,
00116 maxh = 1;
00117 int cspans = 0,
00118 rspanstart = 0,
00119 images = flag & 1,
00120 attrs = flag & 2;
00121 unsigned short maxw[HTML_MAX_COLUMNS];
00122 short rspans[HTML_MAX_COLUMNS];
00123 char buf[100];
00124 const char *cp;
00125 TGHtmlElement *p, *pEnd;
00126 TGString istr("");
00127 TGString substr("");
00128 TGString imgstr("");
00129 TGString attrstr("");
00130
00131 TGString *str = new TGString("");
00132
00133 if (pTable->fType != Html_TABLE) return str;
00134 if (!(pEnd = pTable->fPEnd)) {
00135 delete str;
00136 return 0;
00137 }
00138
00139 str->Append("{ ");
00140 if (attrs) {
00141 attrstr.Append("{ ");
00142 AppendArglist(&attrstr, pTable);
00143 attrstr.Append("} ");
00144 }
00145 for (j = 0; j < HTML_MAX_COLUMNS; j++) {
00146 maxw[j] = 0;
00147 rspans[j] = 0;
00148 }
00149 nest = 1;
00150 istr.Append("{ ");
00151 p = pTable;
00152 while (p && (p = p->fPNext)) {
00153 if (attrs) {
00154 switch (p->fType) {
00155 case Html_EndTR:
00156 break;
00157
00158 case Html_TR:
00159 break;
00160 }
00161 }
00162
00163 switch (p->fType) {
00164 case Html_TABLE:
00165 if (!(p = FindEndNest(p, Html_EndTABLE, 0))) {
00166 delete str;
00167 return 0;
00168 }
00169 break;
00170
00171 case Html_EndTABLE:
00172 p = 0;
00173 break;
00174
00175 case Html_TR:
00176 if (cols > numcols) numcols = cols;
00177 maxh = 1;
00178 cols = 0;
00179 rows++;
00180 nest++;
00181 str->Append("{ ");
00182 if (attrs) {
00183 attrstr.Append("{ { ");
00184 AppendArglist(&attrstr, (TGHtmlMarkupElement *) p);
00185 attrstr.Append("} ");
00186 }
00187 break;
00188
00189 case Html_EndTR:
00190 snprintf(buf, 100, "%d ", maxh);
00191 istr.Append(buf);
00192 if (attrs) {
00193 attrstr.Append("} ");
00194 }
00195 while (nest > 1) {
00196 nest--;
00197 str->Append("} ");
00198 }
00199 break;
00200
00201 case Html_TD:
00202 case Html_TH:
00203 if ((!(cp = p->MarkupArg("colspan", 0))) || (cspans = atoi(cp)) <= 0) {
00204 cspans = 1;
00205 }
00206 if ((cp = p->MarkupArg("rowspan", 0)) && (j = atoi(cp)) > 0 &&
00207 cols < HTML_MAX_COLUMNS) {
00208 rspans[cols] = j;
00209 rspanstart = 1;
00210 } else {
00211 rspanstart = 0;
00212 }
00213 if (attrs) {
00214 j = 0;
00215 while ((cspans - j) > 0) {
00216 attrstr.Append("{ ");
00217 if (!j) AppendArglist(&attrstr, (TGHtmlMarkupElement *) p);
00218 attrstr.Append("} ");
00219 j++;
00220 }
00221 }
00222 cols++;
00223 substr = "";
00224 break;
00225
00226 case Html_EndTD:
00227 case Html_EndTH:
00228 if (!rspanstart) {
00229 while (cols <= HTML_MAX_COLUMNS && rspans[cols-1]-- > 1) {
00230 str->Append(" ");
00231 cols++;
00232 }
00233 }
00234 cp = substr.GetString();
00235
00236 j = 0;
00237 while ((cspans - j) > 0) {
00238 str->Append(cp);
00239 str->Append(" ");
00240 if (!j) {
00241 StringHW(cp, &h, &w);
00242 if (h > maxh) maxh = h;
00243 if (cols > 0 && cols <= HTML_MAX_COLUMNS) {
00244 if (w > maxw[cols-1]) {
00245 maxw[cols-1] = w;
00246 }
00247 }
00248 }
00249 j++;
00250 cp = "";
00251 }
00252 cspans = 0;
00253 break;
00254
00255 case Html_Text:
00256 substr.Append(((TGHtmlTextElement *)p)->fZText, -1);
00257 break;
00258
00259 case Html_Space:
00260 for (j = 0; j < p->fCount; j++) {
00261 substr.Append(" ");
00262 }
00263
00264
00265 break;
00266
00267 case Html_BR:
00268 substr.Append("\n");
00269 break;
00270
00271 case Html_CAPTION:
00272 if (!(pEnd = FindEndNest(p, Html_EndCAPTION, 0))) {
00273 p = pEnd;
00274 }
00275 break;
00276
00277 case Html_IMG:
00278 if (!images) break;
00279 snprintf(buf, sizeof(buf), "%d %d %d %d ", rows-1, cols-1,
00280 substr.GetLength(), p->fElId);
00281 imgstr.Append(buf);
00282 break;
00283 }
00284 }
00285
00286 while (nest--) str->Append("} ");
00287 istr.Append("} { ");
00288 for (j = 0; j < numcols && j < HTML_MAX_COLUMNS; j++) {
00289 snprintf(buf, sizeof(buf), "%d ", maxw[j]);
00290 istr.Append(buf);
00291 }
00292 istr.Append("} ");
00293
00294 str->Append(istr.Data());
00295 str->Append(" ");
00296 if (attrs) {
00297 str->Append("{ ");
00298 str->Append(attrstr.Data());
00299 str->Append("} ");
00300 }
00301 if (images) {
00302 str->Append(imgstr.Data());
00303 }
00304
00305 return str;
00306 }
00307
00308
00309 TGHtmlElement *TGHtml::FindEndNest(TGHtmlElement *sp, int en,
00310 TGHtmlElement *lp)
00311 {
00312
00313
00314
00315
00316
00317
00318 TGHtmlElement *p;
00319 int lvl, n;
00320
00321 p = sp->fPNext;
00322 lvl = 0;
00323 n = sp->fType;
00324
00325 while (p) {
00326 if (p == lp) return 0;
00327 if (n == Html_LI) {
00328 if (p->fType == Html_LI || p->fType == Html_EndUL ||
00329 p->fType == Html_EndOL) {
00330 if (p->fPPrev) return p->fPPrev;
00331 return p;
00332 }
00333 } else if (p->fType == n) {
00334 if (n == Html_OPTION) {
00335 if (p->fPPrev) return p->fPPrev;
00336 return p;
00337 }
00338 lvl++;
00339 } else if (p->fType == en) {
00340 if (!lvl--) return p;
00341 }
00342 switch (p->fType) {
00343 case Html_TABLE: p = ((TGHtmlTable *)p)->fPEnd; break;
00344 case Html_FORM: p = ((TGHtmlForm *)p)->fPEnd; break;
00345 default: p = p->fPNext;
00346 }
00347 }
00348
00349 return 0;
00350 }
00351
00352
00353 TGHtmlElement *TGHtml::TableDimensions(TGHtmlTable *pStart, int lineWidth)
00354 {
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 TGHtmlElement *p;
00377 TGHtmlElement *fPNext;
00378 int iCol1 = 0;
00379 int iRow = 0;
00380 TGHtmlElement *inRow = 0;
00381 TGHtmlElement *inCol = 0;
00382 int i, j;
00383 int n;
00384 int minW, maxW, requestedW;
00385 int noWrap;
00386 int colspan;
00387 int rowspan;
00388 const char *z;
00389 int cellSpacing;
00390 int cellPadding;
00391 int tbw;
00392 int cbw;
00393 int hspace;
00394 int separation;
00395 int margin;
00396 int availWidth=0;
00397 int maxTableWidth;
00398 int fromAbove[HTML_MAX_COLUMNS+1];
00399 int min0span[HTML_MAX_COLUMNS+1];
00400 int max0span[HTML_MAX_COLUMNS+1];
00401 int reqW[HTML_MAX_COLUMNS+1];
00402 int hasbg;
00403
00404
00405
00406
00407
00408
00409 int colMin[HTML_MAX_COLUMNS+1][HTML_MAX_COLUMNS+1];
00410 # define ColMin(A,B) colMin[(A)-1][(B)-1]
00411 # define ColReq(A,B) colMin[(B)-1][(A)-1]
00412
00413 if (pStart == 0 || pStart->fType != Html_TABLE) return pStart;
00414
00415 if (pStart->fBgImage) pStart->fHasbg = 1;
00416
00417 TRACE_PUSH(HtmlTrace_Table1);
00418 TRACE(HtmlTrace_Table1, ("Starting TableDimensions... %s\n",
00419 pStart->MarkupArg("name", "")));
00420
00421 pStart->fNCol = 0;
00422 pStart->fNRow = 0;
00423
00424 z = pStart->MarkupArg("border", 0);
00425 if (z && *z == 0) z = "2";
00426
00427 tbw = z ? atoi(z) : DFLT_BORDER;
00428 if (fTableBorderMin && tbw < fTableBorderMin) tbw = fTableBorderMin;
00429 pStart->fBorderWidth = tbw;
00430
00431 cbw = (tbw > 0);
00432
00433 z = pStart->MarkupArg("cellpadding", 0);
00434 cellPadding = z ? atoi(z) : DFLT_CELLPADDING;
00435 cellSpacing = CellSpacing(pStart);
00436
00437 #ifdef DEBUG
00438
00439
00440
00441 if (HtmlTraceMask & HtmlTrace_Table4) {
00442 tbw = pStart->fBorderWidth = 2;
00443 cbw = 1;
00444 cellPadding = 5;
00445 cellSpacing = 2;
00446 pStart->fStyle.fBgcolor = COLOR_Background;
00447 }
00448 #endif
00449
00450 separation = cellSpacing + 2 * (cellPadding + cbw);
00451 margin = tbw + cellSpacing + cbw + cellPadding;
00452
00453 z = pStart->MarkupArg("hspace", 0);
00454 hspace = z ? atoi(z) : DFLT_HSPACE;
00455
00456
00457 z = pStart->MarkupArg("width", 0);
00458 if (z) {
00459 int len = strlen(z);
00460 if (len > 0 && z[len-1] == '%') {
00461 maxTableWidth = (atoi(z) * lineWidth) / 100;
00462 } else {
00463 maxTableWidth = atoi(z);
00464 }
00465 } else {
00466 maxTableWidth = lineWidth;
00467 }
00468 maxTableWidth -= 2 * margin;
00469 SETMAX(maxTableWidth, 1);
00470
00471 TRACE(HtmlTrace_Table1, ("lineWidth = %d, maxTableWidth = %d, margin = %d\n",
00472 lineWidth, maxTableWidth, margin));
00473
00474 for (p = pStart->fPNext; p; p = fPNext) {
00475 if (p->fType == Html_EndTABLE) {
00476 ((TGHtmlRef *)p)->fPOther = pStart;
00477 pStart->fPEnd = p;
00478 break;
00479 }
00480
00481 fPNext = p->fPNext;
00482
00483 switch (p->fType) {
00484 case Html_EndTD:
00485 case Html_EndTH:
00486 case Html_EndTABLE:
00487 ((TGHtmlRef *)p)->fPOther = pStart;
00488 inCol = 0;
00489 break;
00490
00491 case Html_EndTR:
00492 ((TGHtmlRef *)p)->fPOther = pStart;
00493 inRow = 0;
00494 break;
00495
00496 case Html_TR:
00497 ((TGHtmlRef *)p)->fPOther = pStart;
00498 iRow++;
00499 pStart->fNRow++;
00500 iCol1 = 0;
00501 inRow = p;
00502 availWidth = maxTableWidth;
00503 break;
00504
00505 case Html_CAPTION:
00506 while (p && p->fType != Html_EndTABLE
00507 && p->fType != Html_EndCAPTION) p = p->fPNext;
00508 break;
00509
00510 case Html_TD:
00511 case Html_TH: {
00512 TGHtmlCell *cell = (TGHtmlCell *) p;
00513 inCol = p;
00514 if (!inRow) {
00515
00516 TGHtmlElement *pNew = new TGHtmlRef(Html_TR, 1, 0, 0);
00517 if (pNew == 0) break;
00518
00519 pNew->fCount = 0;
00520 pNew->fStyle = p->fStyle;
00521 pNew->fFlags = p->fFlags;
00522 pNew->fPNext = p;
00523 p->fPPrev->fPNext = pNew;
00524 p->fPPrev = pNew;
00525 fPNext = pNew;
00526 break;
00527 }
00528 do {
00529 iCol1++;
00530 } while (iCol1 <= pStart->fNCol && fromAbove[iCol1] > iRow);
00531 cell->fPTable = pStart;
00532 cell->fPRow = inRow;
00533 colspan = cell->fColspan;
00534 if (colspan == 0) colspan = 1;
00535 if (iCol1 + colspan - 1 > pStart->fNCol) {
00536 int nCol = iCol1 + colspan - 1;
00537 if (nCol > HTML_MAX_COLUMNS) nCol = HTML_MAX_COLUMNS;
00538 for (i = pStart->fNCol + 1; i <= nCol; i++) {
00539 fromAbove[i] = 0;
00540 pStart->fMinW[i] = 0;
00541 pStart->fMaxW[i] = 0;
00542 min0span[i] = 0;
00543 max0span[i] = 0;
00544 reqW[i] = 0;
00545 for (j = 1; j < i; j++) {
00546 ColMin(j,i) = 0;
00547 ColReq(j,i) = 0;
00548 }
00549 }
00550 pStart->fNCol = nCol;
00551 }
00552 noWrap = (p->MarkupArg("nowrap", 0) != 0);
00553 hasbg = (pStart->fHasbg || ((TGHtmlRef *)cell->fPRow)->fBgImage ||
00554 cell->fBgImage);
00555 fPNext = MinMax(p, &minW, &maxW, availWidth, hasbg);
00556 cell->fPEnd = fPNext;
00557 requestedW = 0;
00558 if ((z = p->MarkupArg("width", 0)) != 0) {
00559 for (i = 0; isdigit(z[i]) || z[i] == '.'; i++) {}
00560 if (strcmp(z, "*") == 0) {
00561 requestedW = availWidth;
00562 } else if (z[i] == 0) {
00563 requestedW = atoi(z);
00564 } else if (z[i] == '%') {
00565 requestedW = (atoi(z) * maxTableWidth + 99) / 100;
00566 }
00567 }
00568
00569 TRACE(HtmlTrace_Table1,
00570 ("Row %d Column %d: min=%d max=%d req=%d stop at %s\n",
00571 iRow, iCol1, minW, maxW, requestedW,
00572 GetTokenName(((TGHtmlCell *)p)->fPEnd)));
00573
00574 if (noWrap) {
00575 if ((z = p->MarkupArg("rowspan", 0)) == 0) {
00576
00577 } else {
00578 minW = maxW;
00579 }
00580 }
00581 if (iCol1 + cell->fColspan <= HTML_MAX_COLUMNS) {
00582 int min = 0;
00583 if (cell->fColspan == 0) {
00584 SETMAX(min0span[iCol1], minW);
00585 SETMAX(max0span[iCol1], maxW);
00586 min = min0span[iCol1] + separation;
00587 } else if (colspan == 1) {
00588 SETMAX(pStart->fMinW[iCol1], minW);
00589 SETMAX(pStart->fMaxW[iCol1], maxW);
00590 SETMAX(reqW[iCol1], requestedW);
00591 min = pStart->fMinW[iCol1] + separation;
00592 } else {
00593 int n2 = cell->fColspan;
00594 int per = maxW / n2;
00595 int ix;
00596 SETMAX(ColMin(iCol1, iCol1+n2-1), minW);
00597 SETMAX(ColReq(iCol1, iCol1+n2-1), requestedW);
00598 min = minW + separation;
00599 for (ix = iCol1; ix < iCol1 + n2; ix++) {
00600 if (minW != maxW) {
00601 SETMAX(pStart->fMaxW[ix], per);
00602 }
00603 }
00604 }
00605 availWidth -= min;
00606 }
00607 rowspan = cell->fRowspan;
00608 if (rowspan == 0) rowspan = LARGE_NUMBER;
00609 if (rowspan > 1) {
00610 for (i = iCol1; i < iCol1 + cell->fColspan && i < HTML_MAX_COLUMNS; i++) {
00611 fromAbove[i] = iRow + rowspan;
00612 }
00613 }
00614 if (cell->fColspan > 1) {
00615 iCol1 += cell->fColspan - 1;
00616 } else if (cell->fColspan == 0) {
00617 iCol1 = HTML_MAX_COLUMNS + 1;
00618 }
00619 break;
00620 }
00621 }
00622 }
00623
00624 #ifdef DEBUG
00625 if (HtmlTraceMask & HtmlTrace_Table6) {
00626 const char *zSpace = "";
00627 TRACE_INDENT;
00628 for (i = 1; i <= pStart->fNCol; i++) {
00629 printf("%s%d:%d..%d", zSpace, i, pStart->fMinW[i], pStart->fMaxW[i]);
00630 if (reqW[i] > 0) {
00631 printf("(w=%d)", reqW[i]);
00632 }
00633 zSpace = " ";
00634 }
00635 printf("\n");
00636 for (i = 1; i < pStart->fNCol; i++) {
00637 for (j = i+1; j <= pStart->fNCol; j++) {
00638 if (ColMin(i, j) > 0) {
00639 TRACE_INDENT;
00640 printf("ColMin(%d,%d) = %d\n", i, j, ColMin(i, j));
00641 }
00642 if (ColReq(i, j) > 0) {
00643 TRACE_INDENT;
00644 printf("ColReq(%d,%d) = %d\n", i, j, ColReq(i, j));
00645 }
00646 }
00647 }
00648 }
00649 #endif
00650
00651
00652
00653 for (i = 1; i <= pStart->fNCol; i++) {
00654 int sumMin, sumReq, sumMax;
00655
00656
00657 if (reqW[i] > 0) {
00658 pStart->fMaxW[i] = MAX(pStart->fMinW[i], reqW[i]);
00659 }
00660
00661
00662
00663 if (min0span[i] > 0 || max0span[i] > 0) {
00664 int n2 = pStart->fNCol - i + 1;
00665 minW = (min0span[i] + (n2 - 1) * (1 - separation)) / n2;
00666 maxW = (max0span[i] + (n2 - 1) * (1 - separation)) / n2;
00667 for (j = i; j <= pStart->fNCol; j++) {
00668 SETMAX(pStart->fMinW[j], minW);
00669 SETMAX(pStart->fMaxW[j], maxW);
00670 }
00671 }
00672
00673
00674
00675
00676
00677
00678 sumReq = reqW[i];
00679 sumMin = pStart->fMinW[i];
00680 sumMax = pStart->fMaxW[i];
00681 for (j = i-1; j >= 1; j--) {
00682 int cmin, creq;
00683
00684 sumMin += pStart->fMinW[j];
00685 sumMax += pStart->fMaxW[j];
00686 sumReq += reqW[i];
00687 cmin = ColMin(j, i);
00688
00689 if (cmin > sumMin) {
00690 int k;
00691 double scale;
00692
00693 int *tminW = pStart->fMinW;
00694 int *tmaxW = pStart->fMaxW;
00695 if (sumMin < sumMax) {
00696 scale = (double) (cmin - sumMin) / (double) (sumMax - sumMin);
00697 for (k = j; k <= i; k++) {
00698 sumMin -= tminW[k];
00699 tminW[k] = (int) ((tmaxW[k] - tminW[k]) * scale + tminW[k]);
00700 sumMin += tminW[k];
00701 }
00702 } else if (sumMin > 0) {
00703 scale = (double) cmin / (double) sumMin;
00704 for (k = j; k <= i; k++) {
00705 sumMin -= tminW[k];
00706 tminW[k] = tmaxW[k] = (int) (tminW[k] * scale);
00707 sumMin += tminW[k];
00708 }
00709 } else {
00710 int unit = cmin / (i - j + 1);
00711 for (k = j; k <= i; k++) {
00712 tminW[k] = tmaxW[k] = unit;
00713 sumMin += tminW[k];
00714 }
00715 }
00716 }
00717
00718 creq = ColReq(j, i);
00719 if (creq > sumReq) {
00720 int k;
00721 double scale;
00722
00723 int *tmaxW = pStart->fMaxW;
00724 if (sumReq < sumMax) {
00725 scale = (double) (creq - sumReq) / (double) (sumMax - sumReq);
00726 for (k = j; k <= i; k++) {
00727 sumReq -= reqW[k];
00728 reqW[k] = (int) ((tmaxW[k] - reqW[k]) * scale + reqW[k]);
00729 sumReq += reqW[k];
00730 }
00731 } else if (sumReq > 0) {
00732 scale = (double) creq / (double) sumReq;
00733 for (k = j; k <= i; k++) {
00734 sumReq -= reqW[k];
00735 reqW[k] = (int) (reqW[k] * scale);
00736 sumReq += reqW[k];
00737 }
00738 } else {
00739 int unit = creq / (i - j + 1);
00740 for (k = j; k <= i; k++) {
00741 reqW[k] = unit;
00742 sumReq += reqW[k];
00743 }
00744 }
00745 }
00746 }
00747 }
00748
00749 #ifdef DEBUG
00750 if (HtmlTraceMask & HtmlTrace_Table6) {
00751 const char *zSpace = "";
00752 TRACE_INDENT;
00753 for (i = 1; i <= pStart->fNCol; i++) {
00754 printf("%s%d:%d..%d", zSpace, i, pStart->fMinW[i], pStart->fMaxW[i]);
00755 if (reqW[i] > 0) {
00756 printf("(w=%d)", reqW[i]);
00757 }
00758 zSpace = " ";
00759 }
00760 printf("\n");
00761 }
00762 #endif
00763
00764
00765
00766 n = pStart->fNCol;
00767 requestedW = tbw * 2 + (n + 1) * cellSpacing + n * 2 * (cellPadding + cbw);
00768 pStart->fMinW[0] = requestedW;
00769 pStart->fMaxW[0] = requestedW;
00770 for (i = 1; i <= pStart->fNCol; i++) {
00771 pStart->fMinW[0] += pStart->fMinW[i];
00772 pStart->fMaxW[0] += pStart->fMaxW[i];
00773 requestedW += MAX(reqW[i], pStart->fMinW[i]);
00774 }
00775
00776
00777 z = pStart->MarkupArg("width", 0);
00778 if (z) {
00779 int len = strlen(z);
00780 int totalWidth;
00781 if (len > 0 && z[len-1] == '%') {
00782 totalWidth = (atoi(z) * lineWidth) / 100;
00783 } else {
00784 totalWidth = atoi(z);
00785 }
00786 SETMAX(totalWidth, pStart->fMinW[0]);
00787 #if 1
00788 requestedW = totalWidth;
00789 #else
00790 SETMAX(requestedW, totalWidth);
00791 #endif
00792 }
00793 SETMAX(maxTableWidth, pStart->fMinW[0]);
00794 if (lineWidth && (requestedW > lineWidth)) {
00795
00796 TRACE(HtmlTrace_Table5, ("RequestedW reduced to lineWidth: %d -> %d\n",
00797 requestedW, lineWidth));
00798
00799 requestedW = lineWidth;
00800 }
00801 if (requestedW > pStart->fMinW[0]) {
00802 float scale;
00803 int *tminW = pStart->fMinW;
00804 int *tmaxW = pStart->fMaxW;
00805
00806 TRACE(HtmlTrace_Table5,
00807 ("Expanding table minW from %d to %d. (reqW=%d width=%s)\n",
00808 tminW[0], requestedW, requestedW, z));
00809
00810 if (tmaxW[0] > tminW[0]) {
00811 scale = (double) (requestedW - tminW[0]) / (double) (tmaxW[0] - tminW[0]);
00812 for (i = 1; i <= pStart->fNCol; i++) {
00813 tminW[i] += (int) ((tmaxW[i] - tminW[i]) * scale);
00814 SETMAX(tmaxW[i], tminW[i]);
00815 }
00816 } else if (tminW[0] > 0) {
00817 scale = requestedW / (double) tminW[0];
00818 for (i = 1; i <= pStart->fNCol; i++) {
00819 tminW[i] = (int) (tminW[i] * scale);
00820 tmaxW[i] = (int) (tmaxW[i] * scale);
00821 }
00822 } else if (pStart->fNCol > 0) {
00823 int unit = (requestedW - margin) / pStart->fNCol - separation;
00824 if (unit < 0) unit = 0;
00825 for (i = 1; i <= pStart->fNCol; i++) {
00826 tminW[i] = tmaxW[i] = unit;
00827 }
00828 } else {
00829 tminW[0] = tmaxW[0] = requestedW;
00830 }
00831 pStart->fMinW[0] = requestedW;
00832 SETMAX(pStart->fMaxW[0], requestedW);
00833 }
00834
00835 #ifdef DEBUG
00836 if (HtmlTraceMask & HtmlTrace_Table5) {
00837 TRACE_INDENT;
00838 printf("Start with %s and ", GetTokenName(pStart));
00839 printf("end with %s\n", GetTokenName(p));
00840 TRACE_INDENT;
00841 printf("nCol=%d minWidth=%d maxWidth=%d\n",
00842 pStart->fNCol, pStart->fMinW[0], pStart->fMaxW[0]);
00843 for (i = 1; i <= pStart->fNCol; i++) {
00844 TRACE_INDENT;
00845 printf("Column %d minWidth=%d maxWidth=%d\n",
00846 i, pStart->fMinW[i], pStart->fMaxW[i]);
00847 }
00848 }
00849 #endif
00850
00851 TRACE(HtmlTrace_Table1,
00852 ("Result of TableDimensions: min=%d max=%d nCol=%d\n",
00853 pStart->fMinW[0], pStart->fMaxW[0], pStart->fNCol));
00854 TRACE_POP(HtmlTrace_Table1);
00855
00856 return p;
00857 }
00858
00859
00860 TGHtmlElement *TGHtml::MinMax(TGHtmlElement *p, int *pMin, int *pMax,
00861 int , int hasbg)
00862 {
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 int min = 0;
00882 int max = 0;
00883 int indent = 0;
00884 int obstacle = 0;
00885 int x1 = 0;
00886 int x2 = 0;
00887 int x3 = 0;
00888 int go = 1;
00889 int inpre = 0;
00890 TGHtmlElement *fPNext;
00891 int wstyle = 0;
00892
00893 if (p->MarkupArg("nowrap", 0) != 0) {
00894 wstyle |= STY_NoBreak;
00895 }
00896
00897 for (p = p->fPNext; go && p; p = fPNext) {
00898 fPNext = p->fPNext;
00899 if (!inpre) x3 = 0;
00900 switch (p->fType) {
00901 case Html_PRE:
00902 inpre = 1;
00903 break;
00904
00905 case Html_EndPRE:
00906 inpre = 0;
00907 break;
00908
00909 case Html_Text: {
00910 TGHtmlTextElement *text = (TGHtmlTextElement *) p;
00911 x1 += text->fW;
00912 x2 += text->fW;
00913 SETMAX(max, x1);
00914 if (p->fStyle.fFlags & STY_Preformatted) {
00915 x3 += text->fW;
00916 SETMAX(min, x3);
00917 } else {
00918 SETMAX(min, x2);
00919 }
00920 break;
00921 }
00922
00923 case Html_Space: {
00924 TGHtmlSpaceElement *space = (TGHtmlSpaceElement *) p;
00925 p->fStyle.fFlags |= wstyle;
00926 if (p->fStyle.fFlags & STY_Preformatted) {
00927 if (p->fFlags & HTML_NewLine) {
00928 x1 = x2 = x3 = indent;
00929 } else {
00930 x1 += space->fW * p->fCount;
00931 x2 += space->fW * p->fCount;
00932 x3 += space->fW * p->fCount;
00933 }
00934 } else if (p->fStyle.fFlags & STY_NoBreak) {
00935 if (x1 > indent) x1 += space->fW;
00936 if (x2 > indent) x2 += space->fW;
00937 } else {
00938 if (x1 > indent) x1 += space->fW;
00939 x2 = indent;
00940 }
00941 break;
00942 }
00943
00944 case Html_IMG: {
00945 TGHtmlImageMarkup *image = (TGHtmlImageMarkup *) p;
00946 switch (image->fAlign) {
00947 case IMAGE_ALIGN_Left:
00948 case IMAGE_ALIGN_Right:
00949 obstacle += image->fW;
00950 x1 = obstacle + indent;
00951 x2 = indent;
00952 SETMAX(min, x2);
00953 SETMAX(min, image->fW);
00954 SETMAX(max, x1);
00955 break;
00956
00957 default:
00958 x1 += image->fW;
00959 x2 += image->fW;
00960 if (p->fStyle.fFlags & STY_Preformatted) {
00961 SETMAX(min, x1);
00962 SETMAX(max, x1);
00963 } else {
00964 SETMAX(min, x2);
00965 SETMAX(max, x1);
00966 }
00967 break;
00968 }
00969 break;
00970 }
00971
00972 case Html_TABLE: {
00973 TGHtmlTable *table = (TGHtmlTable *) p;
00974
00975 table->fHasbg = hasbg;
00976 fPNext = TableDimensions(table, 0);
00977 x1 = table->fMaxW[0] + indent + obstacle;
00978 x2 = table->fMinW[0] + indent;
00979 SETMAX(max, x1);
00980 SETMAX(min, x2);
00981 x1 = indent + obstacle;
00982 x2 = indent;
00983 if (fPNext && fPNext->fType == Html_EndTABLE) fPNext = fPNext->fPNext;
00984 break;
00985 }
00986
00987 case Html_UL:
00988 case Html_OL:
00989 indent += HTML_INDENT;
00990 x1 = indent + obstacle;
00991 x2 = indent;
00992 break;
00993
00994 case Html_EndUL:
00995 case Html_EndOL:
00996 indent -= HTML_INDENT;
00997 if (indent < 0) indent = 0;
00998 x1 = indent + obstacle;
00999 x2 = indent;
01000 break;
01001
01002 case Html_BLOCKQUOTE:
01003 indent += 2 * HTML_INDENT;
01004 x1 = indent + obstacle;
01005 x2 = indent;
01006 break;
01007
01008 case Html_EndBLOCKQUOTE:
01009 indent -= 2 * HTML_INDENT;
01010 if (indent < 0) indent = 0;
01011 x1 = indent + obstacle;
01012 x2 = indent;
01013 break;
01014
01015 case Html_APPLET:
01016 case Html_INPUT:
01017 case Html_SELECT:
01018 case Html_EMBED:
01019 case Html_TEXTAREA: {
01020 TGHtmlInput *input = (TGHtmlInput *) p;
01021 x1 += input->fW + input->fPadLeft;
01022 if (p->fStyle.fFlags & STY_Preformatted) {
01023 x3 += input->fW + input->fPadLeft;
01024 SETMAX(min, x3);
01025 SETMAX(max, x1);
01026 x2 += input->fW + input->fPadLeft;
01027 } else {
01028 SETMAX(min, indent + input->fW);
01029 SETMAX(max, x1);
01030 x2 = indent;
01031 }
01032 break;
01033 }
01034
01035 case Html_BR:
01036 case Html_P:
01037 case Html_EndP:
01038 case Html_DIV:
01039 case Html_EndDIV:
01040 case Html_H1:
01041 case Html_EndH1:
01042 case Html_H2:
01043 case Html_EndH2:
01044 case Html_H3:
01045 case Html_EndH3:
01046 case Html_H4:
01047 case Html_EndH4:
01048 case Html_H5:
01049 case Html_H6:
01050 x1 = indent + obstacle;
01051 x2 = indent;
01052 break;
01053
01054 case Html_EndTD:
01055 case Html_EndTH:
01056 case Html_CAPTION:
01057 case Html_EndTABLE:
01058 case Html_TD:
01059 case Html_TR:
01060 case Html_TH:
01061 case Html_EndTR:
01062 go = 0;
01063 break;
01064
01065 default:
01066 break;
01067 }
01068
01069 if (!go) break;
01070 }
01071
01072 *pMin = min;
01073 *pMax = max;
01074
01075 return p;
01076 }
01077
01078
01079
01080
01081 #define VAlign_Unknown 0
01082 #define VAlign_Top 1
01083 #define VAlign_Bottom 2
01084 #define VAlign_Center 3
01085 #define VAlign_Baseline 4
01086
01087
01088
01089 int TGHtmlMarkupElement::GetVerticalAlignment(int dflt)
01090 {
01091
01092
01093 const char *z;
01094 int rc;
01095
01096 z = MarkupArg("valign", 0);
01097 if (z == 0) {
01098 rc = dflt;
01099 } else if (strcasecmp(z, "top") == 0) {
01100 rc = VAlign_Top;
01101 } else if (strcasecmp(z, "bottom") == 0) {
01102 rc = VAlign_Bottom;
01103 } else if (strcasecmp(z, "center") == 0) {
01104 rc = VAlign_Center;
01105 } else if (strcasecmp(z, "baseline") == 0) {
01106 rc = VAlign_Baseline;
01107 } else{
01108 rc = dflt;
01109 }
01110
01111 return rc;
01112 }
01113
01114
01115 TGHtmlElement *TGHtmlLayoutContext::TableLayout(TGHtmlTable *pTable)
01116 {
01117
01118
01119
01120 TGHtmlElement *pEnd1;
01121 TGHtmlElement *p;
01122 TGHtmlElement *fPNext;
01123 TGHtmlElement *pCaption;
01124 TGHtmlElement *pEndCaption;
01125 int width;
01126 int cellSpacing;
01127 int cellPadding;
01128 int tbw;
01129 int cbw;
01130 int pad;
01131 const char *z;
01132 int left_margin;
01133 int lineWidth;
01134 int specWidth;
01135 int separation;
01136 int i;
01137 int n;
01138 int btm;
01139 int iRow;
01140 int iCol;
01141 int colspan;
01142 int vspace;
01143 int hspace;
01144 int rowBottom;
01145 int defaultVAlign;
01146 const char *zAlign;
01147 #define N (HTML_MAX_COLUMNS+1)
01148 int y[N];
01149 int x[N];
01150 int w[N];
01151 int ymax[N];
01152 TGHtmlElement *apElem[N];
01153 int firstRow[N];
01154 int lastRow[N];
01155 int valign[N];
01156 TGHtmlLayoutContext savedContext;
01157 TGHtmlLayoutContext cellContext;
01158 #ifdef TABLE_TRIM_BLANK
01159 extern int HtmlLineWasBlank;
01160 #endif // TABLE_TRIM_BLANK
01161
01162 if (pTable == 0 || pTable->fType != Html_TABLE) return pTable;
01163
01164 TRACE_PUSH(HtmlTrace_Table2);
01165 TRACE(HtmlTrace_Table2, ("Starting TableLayout() at %s\n",
01166 fHtml->GetTokenName(pTable)));
01167
01168
01169
01170
01171
01172
01173 ComputeMargins(&left_margin, &btm, &lineWidth);
01174
01175 TRACE(HtmlTrace_Table2, ("...btm=%d left=%d width=%d\n",
01176 btm, left_margin, lineWidth));
01177
01178
01179
01180 pEnd1 = fHtml->TableDimensions(pTable, lineWidth);
01181
01182
01183
01184
01185
01186 if (lineWidth < pTable->fMinW[0]) {
01187 WidenLine(pTable->fMinW[0], &left_margin, &btm, &lineWidth);
01188
01189 TRACE(HtmlTrace_Table2, ("Widen to btm=%d left=%d width=%d\n",
01190 btm, left_margin, lineWidth));
01191 }
01192 savedContext = *this;
01193
01194
01195 z = pTable->MarkupArg("width", 0);
01196 if (z) {
01197 int len = strlen(z);
01198 if (len > 0 && z[len-1] == '%') {
01199 specWidth = (atoi(z) * lineWidth) / 100;
01200 } else {
01201 specWidth = atoi(z);
01202 }
01203 } else {
01204 specWidth = lineWidth;
01205 }
01206 if (specWidth < pTable->fMinW[0]) {
01207 width = pTable->fMinW[0];
01208 } else if (specWidth <= pTable->fMaxW[0]) {
01209 width = specWidth;
01210 } else {
01211 width = pTable->fMaxW[0];
01212 }
01213
01214
01215
01216
01217 z = pTable->MarkupArg("cellpadding", 0);
01218 cellPadding = z ? atoi(z) : DFLT_CELLPADDING;
01219 cellSpacing = fHtml->CellSpacing(pTable);
01220
01221 z = pTable->MarkupArg("vspace", 0);
01222 vspace = z ? atoi(z) : DFLT_VSPACE;
01223
01224 z = pTable->MarkupArg("hspace", 0);
01225 hspace = z ? atoi(z) : DFLT_HSPACE;
01226
01227 #ifdef DEBUG
01228 if (HtmlTraceMask & HtmlTrace_Table4) {
01229 cellPadding = 5;
01230 cellSpacing = 2;
01231 if (vspace < 2) vspace = 2;
01232 if (hspace < 2) hspace = 2;
01233 }
01234 #endif
01235
01236 tbw = pTable->fBorderWidth;
01237 cbw = (tbw > 0);
01238 pad = cellPadding + cbw;
01239 separation = cellSpacing + 2 * pad;
01240 x[1] = left_margin + tbw + cellSpacing + pad;
01241
01242 n = pTable->fNCol;
01243 if (n <= 0 || pTable->fMaxW[0] <= 0) {
01244
01245
01246 return pEnd1;
01247 }
01248
01249 zAlign = pTable->MarkupArg("align", "");
01250 if (width <= lineWidth) {
01251 int align = pTable->fStyle.fAlign;
01252 if (align == ALIGN_Right || strcasecmp(zAlign, "right") == 0) {
01253 x[1] += lineWidth - width;
01254 } else if (align == ALIGN_Center && strcasecmp(zAlign, "left") != 0) {
01255 x[1] += (lineWidth - width) / 2;
01256 }
01257 }
01258
01259 if (width == pTable->fMaxW[0]) {
01260 w[1] = pTable->fMaxW[1];
01261 for (i = 2; i <= n; i++) {
01262 w[i] = pTable->fMaxW[i];
01263 x[i] = x[i-1] + w[i-1] + separation;
01264 }
01265 } else if (width > pTable->fMaxW[0]) {
01266 int *tmaxW = pTable->fMaxW;
01267 double scale = ((double) width) / (double) tmaxW[0];
01268 w[1] = (int) (tmaxW[1] * scale);
01269 for (i = 2; i <= n; i++) {
01270 w[i] = (int) (tmaxW[i] * scale);
01271 x[i] = x[i-1] + w[i-1] + separation;
01272 }
01273 } else if (width > pTable->fMinW[0]) {
01274 float scale;
01275 int *tminW = pTable->fMinW;
01276 int *tmaxW = pTable->fMaxW;
01277 scale = (double) (width - tminW[0]) / (double) (tmaxW[0] - tminW[0]);
01278 w[1] = (int) (tminW[1] + (tmaxW[1] - tminW[1]) * scale);
01279 for (i = 2; i <= n; i++) {
01280 w[i] = (int) (tminW[i] + (tmaxW[i] - tminW[i]) * scale);
01281 x[i] = x[i-1] + w[i-1] + separation;
01282 }
01283 } else {
01284 w[1] = pTable->fMinW[1];
01285 for (i = 2; i <= n; i++) {
01286 w[i] = pTable->fMinW[i];
01287 x[i] = x[i-1] + w[i-1] + separation;
01288 }
01289 }
01290 w[n] = width - ((x[n] - x[1]) + 2 * (tbw + pad + cellSpacing));
01291
01292
01293
01294
01295 btm += vspace;
01296 pTable->fY = btm;
01297 pTable->fX = x[1] - (tbw + cellSpacing + pad);
01298 pTable->fW = width;
01299 SETMAX(fMaxX, pTable->fX + pTable->fW);
01300 btm += tbw + cellSpacing;
01301
01302
01303 for (i = 1; i <= n; i++) {
01304 firstRow[i] = 0;
01305 lastRow[i] = 0;
01306 apElem[i] = 0;
01307 }
01308 p = pTable->fPNext;
01309 rowBottom = btm;
01310 for (iRow = 1; iRow <= pTable->fNRow; iRow++) {
01311
01312 TRACE(HtmlTrace_Table2, ("Row %d: btm=%d\n",iRow,btm));
01313
01314
01315
01316 while (p && p->fType != Html_TR) {
01317 if (p->fType == Html_CAPTION) {
01318 pCaption = p;
01319 while (p && p != pEnd1 && p->fType != Html_EndCAPTION) p = p->fPNext;
01320 pEndCaption = p;
01321 }
01322
01323 TRACE(HtmlTrace_Table3, ("Skipping token %s\n", fHtml->GetTokenName(p)));
01324
01325 if (p) p = p->fPNext;
01326 }
01327 if (p == 0) break;
01328
01329
01330 defaultVAlign = p->GetVerticalAlignment(VAlign_Center);
01331
01332
01333 for (iCol = 1; iCol <= pTable->fNCol && iCol <= HTML_MAX_COLUMNS; iCol++) {
01334 if (lastRow[iCol] < iRow) ymax[iCol] = 0;
01335 }
01336 iCol = 0;
01337 for (p = p->fPNext; p && p->fType != Html_TR && p != pEnd1; p = fPNext) {
01338 fPNext = p->fPNext;
01339
01340 TRACE(HtmlTrace_Table3, ("Processing token %s\n", fHtml->GetTokenName(p)));
01341
01342 switch (p->fType) {
01343 case Html_TD:
01344 case Html_TH:
01345
01346
01347 do {
01348 iCol++;
01349 } while (iCol <= HTML_MAX_COLUMNS && lastRow[iCol] >= iRow);
01350
01351 TRACE(HtmlTrace_Table2,
01352 ("Column %d: x=%d w=%d\n",iCol,x[iCol],w[iCol]));
01353
01354
01355
01356 if (iCol <= HTML_MAX_COLUMNS) {
01357 TGHtmlCell *cell = (TGHtmlCell *) p;
01358 apElem[iCol] = p;
01359 fPNext = cell->fPEnd;
01360 if (cell->fRowspan == 0) {
01361 lastRow[iCol] = pTable->fNRow;
01362 } else {
01363 lastRow[iCol] = iRow + cell->fRowspan - 1;
01364 }
01365 firstRow[iCol] = iRow;
01366
01367
01368 valign[iCol] = p->GetVerticalAlignment(defaultVAlign);
01369
01370
01371 y[iCol] = btm + pad;
01372 cellContext.fHtml = fHtml;
01373 cellContext.fPStart = p->fPNext;
01374 cellContext.fPEnd = fPNext;
01375 cellContext.fHeadRoom = 0;
01376 cellContext.fTop = y[iCol];
01377 cellContext.fBottom = y[iCol];
01378 cellContext.fLeft = x[iCol];
01379 cellContext.fRight = 0;
01380 cellContext.fPageWidth = x[iCol] + w[iCol];
01381 colspan = cell->fColspan;
01382 if (colspan == 0) {
01383 for (i = iCol + 1;
01384 i <= pTable->fNCol && i <= HTML_MAX_COLUMNS; i++) {
01385 cellContext.fPageWidth += w[i] + separation;
01386 lastRow[i] = lastRow[iCol];
01387 }
01388 } else if (colspan > 1) {
01389 for (i = iCol + 1;
01390 i < iCol + colspan && i <= HTML_MAX_COLUMNS; i++) {
01391 cellContext.fPageWidth += w[i] + separation;
01392 lastRow[i] = lastRow[iCol];
01393 }
01394 }
01395 cellContext.fMaxX = 0;
01396 cellContext.fMaxY = 0;
01397 cellContext.fLeftMargin = 0;
01398 cellContext.fRightMargin = 0;
01399 cellContext.LayoutBlock();
01400 #ifdef TABLE_TRIM_BLANK
01401
01402
01403 if (HtmlLineWasBlank) {
01404 cellContext.fMaxY -= cellContext.headRoom;
01405 }
01406 #endif // TABLE_TRIM_BLANK
01407 ymax[iCol] = cellContext.fMaxY;
01408 SETMAX(ymax[iCol], y[iCol]);
01409 cellContext.ClearMarginStack(&cellContext.fLeftMargin);
01410 cellContext.ClearMarginStack(&cellContext.fRightMargin);
01411
01412
01413 cell->fX = x[iCol] - pad;
01414 cell->fY = btm;
01415 cell->fW = cellContext.fPageWidth + 2 * pad - x[iCol];
01416
01417 TRACE(HtmlTrace_Table2,
01418 ("Column %d top=%d bottom=%d h=%d left=%d w=%d\n",
01419 iCol, y[iCol], ymax[iCol], ymax[iCol]-y[iCol],
01420 cell->fX, cell->fW));
01421
01422
01423 if (colspan > 1) {
01424 iCol += colspan - 1;
01425 } else if (colspan == 0) {
01426 iCol = HTML_MAX_COLUMNS + 1;
01427 }
01428 }
01429 break;
01430
01431 case Html_CAPTION:
01432
01433
01434 pCaption = p;
01435 while (fPNext && fPNext != pEnd1 && fPNext->fType != Html_EndCAPTION) {
01436 fPNext = fPNext->fPNext;
01437 }
01438 pEndCaption = fPNext;
01439 break;
01440 }
01441 }
01442
01443
01444 for (iCol = 1; iCol <= pTable->fNCol; iCol++) {
01445 if (lastRow[iCol] == iRow || iRow == pTable->fNRow) {
01446 SETMAX(rowBottom, ymax[iCol]);
01447 }
01448 }
01449
01450 TRACE(HtmlTrace_Table2, ("Total row height: %d..%d -> %d\n",
01451 btm,rowBottom,rowBottom-btm));
01452
01453
01454 for (iCol = 1; iCol <= pTable->fNCol; iCol++) {
01455 int dy = 0;
01456 TGHtmlCell *apCell = (TGHtmlCell *) apElem[iCol];
01457
01458
01459
01460 if (apElem[iCol] == 0 ||
01461 (iRow != pTable->fNRow && lastRow[iCol] > iRow)) continue;
01462
01463
01464 switch (valign[iCol]) {
01465 case VAlign_Unknown:
01466 case VAlign_Center:
01467 dy = (rowBottom - ymax[iCol])/2;
01468 break;
01469 case VAlign_Top:
01470 case VAlign_Baseline:
01471 dy = 0;
01472 break;
01473 case VAlign_Bottom:
01474 dy = rowBottom - ymax[iCol];
01475 break;
01476 }
01477 if (dy) {
01478 TGHtmlElement *pLast = apCell->fPEnd;
01479
01480 TRACE(HtmlTrace_Table3, ("Delta column %d by %d\n",iCol,dy));
01481
01482 fHtml->MoveVertically(apElem[iCol]->fPNext, pLast, dy);
01483 }
01484
01485
01486 apCell->fH = rowBottom + pad - apCell->fY;
01487 apElem[iCol] = 0;
01488 }
01489
01490
01491 btm = rowBottom + pad + cellSpacing;
01492 }
01493
01494 btm += tbw;
01495 pTable->fH = btm - pTable->fY;
01496 SETMAX(fMaxY, btm);
01497 fBottom = btm + vspace;
01498
01499
01500 if (pCaption) {
01501 }
01502
01503
01504
01505 fHtml->ResetBlocks();
01506
01507
01508
01509
01510 if (strcasecmp(zAlign, "left") == 0) {
01511 savedContext.fMaxX = fMaxX;
01512 savedContext.fMaxY = fMaxY;
01513 *this = savedContext;
01514 PushMargin(&fLeftMargin, pTable->fW + 2, pTable->fY + pTable->fH + 2, 0);
01515 } else if (strcasecmp(zAlign, "right") == 0) {
01516 savedContext.fMaxX = fMaxX;
01517 savedContext.fMaxY = fMaxY;
01518 *this = savedContext;
01519 PushMargin(&fRightMargin, pTable->fW + 2, pTable->fY + pTable->fH + 2, 0);
01520 }
01521
01522
01523
01524 TRACE(HtmlTrace_Table2, (
01525 "Done with TableLayout(). x=%d y=%d w=%d h=%d Return %s\n",
01526 pTable->fX, pTable->fY, pTable->fW, pTable->fH,
01527 fHtml->GetTokenName(pEnd1)));
01528 TRACE_POP(HtmlTrace_Table2);
01529
01530 return pEnd1;
01531 }
01532
01533
01534 void TGHtml::MoveVertically(TGHtmlElement *p, TGHtmlElement *pLast1, int dy)
01535 {
01536
01537
01538
01539
01540
01541
01542 if (dy == 0) return;
01543
01544 while (p && p != pLast1) {
01545 switch (p->fType) {
01546 case Html_A:
01547 ((TGHtmlAnchor *)p)->fY += dy;
01548 break;
01549
01550 case Html_Text:
01551 ((TGHtmlTextElement *)p)->fY += dy;
01552 break;
01553
01554 case Html_LI:
01555 ((TGHtmlLi *)p)->fY += dy;
01556 break;
01557
01558 case Html_TD:
01559 case Html_TH:
01560 ((TGHtmlCell *)p)->fY += dy;
01561 break;
01562
01563 case Html_TABLE:
01564 ((TGHtmlTable *)p)->fY += dy;
01565 break;
01566
01567 case Html_IMG:
01568 ((TGHtmlImageMarkup *)p)->fY += dy;
01569 break;
01570
01571 case Html_INPUT:
01572 case Html_SELECT:
01573 case Html_APPLET:
01574 case Html_EMBED:
01575 case Html_TEXTAREA:
01576 ((TGHtmlInput *)p)->fY += dy;
01577 break;
01578
01579 default:
01580 break;
01581 }
01582 p = p->fPNext;
01583 }
01584 }