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)) 
   53 int TGHtml::CellSpacing(TGHtmlElement *pTable)
 
   59    z = pTable->MarkupArg(
"cellspacing", 0);
 
   61       relief = fTableRelief;
 
   62       if (relief == HTML_RELIEF_RAISED || relief == HTML_RELIEF_SUNKEN) {
 
   63          cellSpacing = DFLT_CELLSPACING_3D;
 
   65          cellSpacing = DFLT_CELLSPACING_FLAT;
 
   68       cellSpacing = atoi(z);
 
   77 void TGHtml::StringHW(
const char *str, 
int *h, 
int *w)
 
   80    int nw = 0, nh = 1, mw = 0;
 
  108 TGString *TGHtml::TableText(TGHtmlTable *pTable, 
int flag)
 
  121    unsigned short maxw[HTML_MAX_COLUMNS];
 
  122    short rspans[HTML_MAX_COLUMNS];
 
  125    TGHtmlElement *p, *pEnd;
 
  129    TGString attrstr(
"");  
 
  131    TGString *str = 
new TGString(
"");  
 
  133    if (pTable->fType != Html_TABLE) 
return str;
 
  134    if (!(pEnd = pTable->fPEnd)) {
 
  141       attrstr.Append(
"{ ");  
 
  142       AppendArglist(&attrstr, pTable);
 
  143       attrstr.Append(
"} ");  
 
  145    for (j = 0; j < HTML_MAX_COLUMNS; j++) {
 
  152    while (p && (p = p->fPNext)) {
 
  165             if (!(p = FindEndNest(p, Html_EndTABLE, 0))) {
 
  176             if (cols > numcols) numcols = cols;
 
  183                attrstr.Append(
"{ { ");
 
  184                AppendArglist(&attrstr, (TGHtmlMarkupElement *) p);
 
  185                attrstr.Append(
"} ");
 
  190             snprintf(buf, 100, 
"%d ", maxh);
 
  193                attrstr.Append(
"} ");
 
  203             if ((!(cp = p->MarkupArg(
"colspan", 0))) || (cspans = atoi(cp)) <= 0) {
 
  206             if ((cp = p->MarkupArg(
"rowspan", 0)) && (j = atoi(cp)) > 0 &&
 
  207                 cols < HTML_MAX_COLUMNS) {
 
  215                while ((cspans - j) > 0) {
 
  216                   attrstr.Append(
"{ ");
 
  217                   if (!j) AppendArglist(&attrstr, (TGHtmlMarkupElement *) p);
 
  218                   attrstr.Append(
"} ");
 
  229                while (cols <= HTML_MAX_COLUMNS && rspans[cols-1]-- > 1) {
 
  234             cp = substr.GetString();
 
  237             while ((cspans - j) > 0) {
 
  241                   StringHW(cp, &h, &w);
 
  242                   if (h > maxh) maxh = h;
 
  243                   if (cols > 0 && cols <= HTML_MAX_COLUMNS) {
 
  244                      if (w > maxw[cols-1]) {
 
  256             substr.Append(((TGHtmlTextElement *)p)->fZText);
 
  260             for (j = 0; j < p->fCount; j++) {
 
  272             if (!(pEnd = FindEndNest(p, Html_EndCAPTION, 0))) {
 
  279             snprintf(buf, 
sizeof(buf), 
"%d %d %d %d ", rows-1, cols-1,
 
  280                      substr.GetLength(), p->fElId);
 
  286    while (nest--) str->Append(
"} ");
 
  288    for (j = 0; j < numcols && j < HTML_MAX_COLUMNS; j++) {
 
  289       snprintf(buf, 
sizeof(buf), 
"%d ", maxw[j]);
 
  294    str->Append(istr.Data());
 
  298       str->Append(attrstr.Data());
 
  302       str->Append(imgstr.Data());
 
  315 TGHtmlElement *TGHtml::FindEndNest(TGHtmlElement *sp, 
int en,
 
  326       if (p == lp) 
return 0;
 
  328          if (p->fType == Html_LI || p->fType == Html_EndUL ||
 
  329              p->fType == Html_EndOL) {
 
  330             if (p->fPPrev) 
return p->fPPrev;
 
  333       } 
else if (p->fType == n) {
 
  334          if (n == Html_OPTION) {
 
  335             if (p->fPPrev) 
return p->fPPrev;
 
  339       } 
else if (p->fType == en) {
 
  340          if (!lvl--) 
return p;
 
  343          case Html_TABLE: p = ((TGHtmlTable *)p)->fPEnd; 
break; 
 
  344          case Html_FORM:  p = ((TGHtmlForm *)p)->fPEnd;  
break;
 
  345          default: p = p->fPNext;
 
  374 TGHtmlElement *TGHtml::TableDimensions(TGHtmlTable *pStart, 
int lineWidth)
 
  377    TGHtmlElement *fPNext;              
 
  380    TGHtmlElement *inRow = 0;          
 
  383    int minW, maxW, requestedW;        
 
  397    int fromAbove[HTML_MAX_COLUMNS+1]={0}; 
 
  398    int min0span[HTML_MAX_COLUMNS+1]={0}; 
 
  399    int max0span[HTML_MAX_COLUMNS+1]={0}; 
 
  400    int reqW[HTML_MAX_COLUMNS+1]={0};   
 
  408    int colMin[HTML_MAX_COLUMNS+1][HTML_MAX_COLUMNS+1];
 
  409 # define ColMin(A,B) colMin[(A)-1][(B)-1] 
  410 # define ColReq(A,B) colMin[(B)-1][(A)-1] 
  412    if (pStart == 0 || pStart->fType != Html_TABLE) 
return pStart;
 
  414    if (pStart->fBgImage) pStart->fHasbg = 1;
 
  416    TRACE_PUSH(HtmlTrace_Table1);
 
  417    TRACE(HtmlTrace_Table1, (
"Starting TableDimensions... %s\n",
 
  418         pStart->MarkupArg(
"name", 
"")));
 
  423    z = pStart->MarkupArg(
"border", 0);
 
  424    if (z && *z == 0) z = 
"2";
 
  426    tbw = z ? atoi(z) : DFLT_BORDER;
 
  427    if (fTableBorderMin && tbw < fTableBorderMin) tbw = fTableBorderMin;
 
  428    pStart->fBorderWidth = tbw;
 
  432    z = pStart->MarkupArg(
"cellpadding", 0);
 
  433    cellPadding = z ? atoi(z) : DFLT_CELLPADDING;
 
  434    cellSpacing = CellSpacing(pStart);
 
  440    if (HtmlTraceMask & HtmlTrace_Table4) {
 
  441       tbw = pStart->fBorderWidth = 2;
 
  445       pStart->fStyle.fBgcolor = COLOR_Background;
 
  449    separation = cellSpacing + 2 * (cellPadding + cbw);
 
  450    margin = tbw + cellSpacing + cbw + cellPadding;
 
  452    z = pStart->MarkupArg(
"hspace", 0);
 
  456    z = pStart->MarkupArg(
"width", 0);
 
  459       if (len > 0 && z[len-1] == 
'%') {
 
  460          maxTableWidth = (atoi(z) * lineWidth) / 100;
 
  462          maxTableWidth = atoi(z);
 
  465       maxTableWidth = lineWidth;
 
  467    maxTableWidth -= 2 * margin;
 
  468    SETMAX(maxTableWidth, 1);
 
  470    TRACE(HtmlTrace_Table1, (
"lineWidth = %d, maxTableWidth = %d, margin = %d\n",
 
  471          lineWidth, maxTableWidth, margin));
 
  473    for (p = pStart->fPNext; p; p = fPNext) {
 
  474       if (p->fType == Html_EndTABLE) {
 
  475           ((TGHtmlRef *)p)->fPOther = pStart;
 
  486             ((TGHtmlRef *)p)->fPOther = pStart;
 
  491             ((TGHtmlRef *)p)->fPOther = pStart;
 
  496             ((TGHtmlRef *)p)->fPOther = pStart;
 
  501             availWidth = maxTableWidth;
 
  505             while (p && p->fType != Html_EndTABLE
 
  506                    && p->fType != Html_EndCAPTION) p = p->fPNext;
 
  511             TGHtmlCell *cell = (TGHtmlCell *) p;
 
  515                TGHtmlElement *pNew = 
new TGHtmlRef(Html_TR, 1, 0, 0);
 
  516                if (pNew == 0) 
break;
 
  519                pNew->fStyle = p->fStyle;
 
  520                pNew->fFlags = p->fFlags;
 
  522                p->fPPrev->fPNext = pNew;
 
  529             } 
while (iCol1 <= pStart->fNCol && fromAbove[iCol1] > iRow);
 
  530             cell->fPTable = pStart;
 
  532             colspan = cell->fColspan;
 
  533             if (colspan == 0) colspan = 1;
 
  534             if (iCol1 + colspan - 1 > pStart->fNCol) {
 
  535                int nCol = iCol1 + colspan - 1;
 
  536                if (nCol > HTML_MAX_COLUMNS) nCol = HTML_MAX_COLUMNS;
 
  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);
 
  552             hasbg = (pStart->fHasbg || ((TGHtmlRef *)cell->fPRow)->fBgImage ||
 
  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;
 
  568             TRACE(HtmlTrace_Table1,
 
  569                   (
"Row %d Column %d: min=%d max=%d req=%d stop at %s\n",
 
  570                   iRow, iCol1, minW, maxW, requestedW,
 
  571                   GetTokenName(((TGHtmlCell *)p)->fPEnd)));
 
  575                if ((z = p->MarkupArg(
"rowspan", 0)) == 0) { 
 
  581             if (iCol1 + cell->fColspan <= HTML_MAX_COLUMNS) {
 
  583                if (cell->fColspan == 0) {
 
  584                   SETMAX(min0span[iCol1], minW);
 
  585                   SETMAX(max0span[iCol1], maxW);
 
  586                   min = min0span[iCol1] + separation;
 
  587                } 
else if (colspan == 1) {
 
  588                   SETMAX(pStart->fMinW[iCol1], minW);
 
  589                   SETMAX(pStart->fMaxW[iCol1], maxW);
 
  590                   SETMAX(reqW[iCol1], requestedW);
 
  591                   min = pStart->fMinW[iCol1] + separation;
 
  593                   int n2 = cell->fColspan;
 
  596                   SETMAX(ColMin(iCol1, iCol1+n2-1), minW);
 
  597                   SETMAX(ColReq(iCol1, iCol1+n2-1), requestedW);
 
  598                   min = minW + separation;
 
  599                   for (ix = iCol1; ix < iCol1 + n2; ix++) {
 
  601                         SETMAX(pStart->fMaxW[ix], per);
 
  607             rowspan = cell->fRowspan;
 
  608             if (rowspan == 0) rowspan = LARGE_NUMBER;
 
  610                for (i = iCol1; i < iCol1 + cell->fColspan && i < HTML_MAX_COLUMNS; i++) {
 
  611                   fromAbove[i] = iRow + rowspan;
 
  614             if (cell->fColspan > 1) {
 
  615                iCol1 += cell->fColspan - 1;
 
  616             } 
else if (cell->fColspan == 0) {
 
  617                iCol1 = HTML_MAX_COLUMNS + 1;
 
  625    if (HtmlTraceMask & HtmlTrace_Table6) {
 
  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++) {
 
  638             if (ColMin(i, j) > 0) {
 
  640                printf(
"ColMin(%d,%d) = %d\n", i, j, ColMin(i, j));
 
  642             if (ColReq(i, j) > 0) {
 
  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;
 
  658          pStart->fMaxW[i] = MAX(pStart->fMinW[i], reqW[i]);
 
  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++) {
 
  668             SETMAX(pStart->fMinW[j], minW);
 
  669             SETMAX(pStart->fMaxW[j], maxW);
 
  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++) {
 
  750    if (HtmlTraceMask & HtmlTrace_Table6) {
 
  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++) {
 
  771       pStart->fMinW[0] += pStart->fMinW[i];
 
  772       pStart->fMaxW[0] += pStart->fMaxW[i];
 
  773       requestedW += MAX(reqW[i], pStart->fMinW[i]);
 
  777    z = pStart->MarkupArg(
"width", 0);
 
  781       if (len > 0 && z[len-1] == 
'%') {
 
  782          totalWidth = (atoi(z) * lineWidth) / 100;
 
  784          totalWidth = atoi(z);
 
  786       SETMAX(totalWidth, pStart->fMinW[0]);
 
  788       requestedW = totalWidth;
 
  790       SETMAX(requestedW, totalWidth); 
 
  793    SETMAX(maxTableWidth, pStart->fMinW[0]);
 
  794    if (lineWidth && (requestedW > lineWidth)) {
 
  796       TRACE(HtmlTrace_Table5, (
"RequestedW reduced to lineWidth: %d -> %d\n",
 
  797             requestedW, lineWidth));
 
  799       requestedW = lineWidth;
 
  801    if (requestedW > pStart->fMinW[0]) {
 
  803       int *tminW = pStart->fMinW;
 
  804       int *tmaxW = pStart->fMaxW;
 
  806       TRACE(HtmlTrace_Table5,
 
  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;
 
  832       SETMAX(pStart->fMaxW[0], requestedW);
 
  836    if (HtmlTraceMask & HtmlTrace_Table5) {
 
  838       printf(
"Start with %s and ", GetTokenName(pStart));
 
  839       printf(
"end with %s\n", GetTokenName(p));
 
  841       printf(
"nCol=%d minWidth=%d maxWidth=%d\n",
 
  842       pStart->fNCol, pStart->fMinW[0], pStart->fMaxW[0]);
 
  843       for (i = 1; i <= pStart->fNCol; i++) {
 
  845          printf(
"Column %d minWidth=%d maxWidth=%d\n",
 
  846                 i, pStart->fMinW[i], pStart->fMaxW[i]);
 
  851    TRACE(HtmlTrace_Table1,
 
  852          (
"Result of TableDimensions: min=%d max=%d nCol=%d\n",
 
  853           pStart->fMinW[0], pStart->fMaxW[0], pStart->fNCol));
 
  854    TRACE_POP(HtmlTrace_Table1);
 
  878 TGHtmlElement *TGHtml::MinMax(TGHtmlElement *p, 
int *pMin, 
int *pMax,
 
  890    TGHtmlElement *fPNext;     
 
  893    if (p->MarkupArg(
"nowrap", 0) != 0) {
 
  894       wstyle |= STY_NoBreak;
 
  897    for (p = p->fPNext; go && p; p = fPNext) {
 
  910             TGHtmlTextElement *text = (TGHtmlTextElement *) p;
 
  914             if (p->fStyle.fFlags & STY_Preformatted) {
 
  924             TGHtmlSpaceElement *space = (TGHtmlSpaceElement *) p;
 
  925             p->fStyle.fFlags |= wstyle;
 
  926             if (p->fStyle.fFlags & STY_Preformatted) {
 
  927                if (p->fFlags & HTML_NewLine) {
 
  928                   x1 = x2 = x3 = indent;
 
  930                   x1 += space->fW * p->fCount;
 
  931                   x2 += space->fW * p->fCount;
 
  932                   x3 += space->fW * p->fCount;
 
  934             } 
else if (p->fStyle.fFlags & STY_NoBreak) {
 
  935                if (x1 > indent) x1 += space->fW;
 
  936                if (x2 > indent) x2 += space->fW;
 
  938                if (x1 > indent) x1 += space->fW;
 
  945             TGHtmlImageMarkup *image = (TGHtmlImageMarkup *) p;
 
  946             switch (image->fAlign) {
 
  947                case IMAGE_ALIGN_Left:
 
  948                case IMAGE_ALIGN_Right:
 
  949                   obstacle += image->fW;
 
  950                   x1 = obstacle + indent;
 
  953                   SETMAX(min, image->fW);
 
  960                   if (p->fStyle.fFlags & STY_Preformatted) {
 
  973             TGHtmlTable *table = (TGHtmlTable *) p;
 
  975             table->fHasbg = hasbg;
 
  976             fPNext = TableDimensions(table, 0);
 
  977             x1 = table->fMaxW[0] + indent + obstacle;
 
  978             x2 = table->fMinW[0] + indent;
 
  981             x1 = indent + obstacle;
 
  983             if (fPNext && fPNext->fType == Html_EndTABLE) fPNext = fPNext->fPNext;
 
  989             indent += HTML_INDENT;
 
  990             x1 = indent + obstacle;
 
  996             indent -= HTML_INDENT;
 
  997             if (indent < 0) indent = 0;
 
  998             x1 = indent + obstacle;
 
 1002          case Html_BLOCKQUOTE:
 
 1003             indent += 2 * HTML_INDENT;
 
 1004             x1 = indent + obstacle;
 
 1008          case Html_EndBLOCKQUOTE:
 
 1009             indent -= 2 * HTML_INDENT;
 
 1010             if (indent < 0) indent = 0;
 
 1011             x1 = indent + obstacle;
 
 1019          case Html_TEXTAREA: {
 
 1020             TGHtmlInput *input = (TGHtmlInput *) p;
 
 1021             x1 += input->fW + input->fPadLeft;
 
 1022             if (p->fStyle.fFlags & STY_Preformatted) {
 
 1023                x3 += input->fW + input->fPadLeft;
 
 1026                x2 += input->fW + input->fPadLeft;
 
 1028                SETMAX(min, indent + input->fW);
 
 1050             x1 = indent + obstacle;
 
 1081 #define VAlign_Unknown    0 
 1082 #define VAlign_Top        1 
 1083 #define VAlign_Bottom     2 
 1084 #define VAlign_Center     3 
 1085 #define VAlign_Baseline   4 
 1091 int TGHtmlMarkupElement::GetVerticalAlignment(
int dflt)
 
 1096    z = MarkupArg(
"valign", 0);
 
 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) {
 
 1106       rc = VAlign_Baseline;
 
 1118 TGHtmlElement *TGHtmlLayoutContext::TableLayout(TGHtmlTable *pTable)
 
 1120    TGHtmlElement *pEnd1;       
 
 1122    TGHtmlElement *fPNext;       
 
 1123    TGHtmlElement *pCaption=0;  
 
 1147 #define N (HTML_MAX_COLUMNS+1) 
 1152    TGHtmlElement *apElem[N]={0}; 
 
 1156    TGHtmlLayoutContext savedContext;  
 
 1157    TGHtmlLayoutContext cellContext;   
 
 1158 #ifdef TABLE_TRIM_BLANK 
 1159    extern int HtmlLineWasBlank;
 
 1160 #endif // TABLE_TRIM_BLANK 
 1162    if (pTable == 0 || pTable->fType != Html_TABLE) 
return pTable;
 
 1164    TRACE_PUSH(HtmlTrace_Table2);
 
 1165    TRACE(HtmlTrace_Table2, (
"Starting TableLayout() at %s\n",
 
 1166                             fHtml->GetTokenName(pTable)));
 
 1168    for (i=0;i<N;i++) ymax[i]=0;
 
 1175    ComputeMargins(&left_margin, &btm, &lineWidth);
 
 1177    TRACE(HtmlTrace_Table2, (
"...btm=%d left=%d width=%d\n",
 
 1178                            btm, left_margin, lineWidth));
 
 1182    pEnd1 = fHtml->TableDimensions(pTable, lineWidth);
 
 1188    if (lineWidth < pTable->fMinW[0]) {
 
 1189       WidenLine(pTable->fMinW[0], &left_margin, &btm, &lineWidth);
 
 1191       TRACE(HtmlTrace_Table2, (
"Widen to btm=%d left=%d width=%d\n",
 
 1192                              btm, left_margin, lineWidth));
 
 1194    savedContext = *
this;
 
 1197    z = pTable->MarkupArg(
"width", 0);
 
 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]) {
 
 1209       width = pTable->fMinW[0];
 
 1210    } 
else if (specWidth <= pTable->fMaxW[0]) {
 
 1213       width = pTable->fMaxW[0];
 
 1219    z = pTable->MarkupArg(
"cellpadding", 0);
 
 1220    cellPadding = z ? atoi(z) : DFLT_CELLPADDING;
 
 1221    cellSpacing = fHtml->CellSpacing(pTable);
 
 1223    z = pTable->MarkupArg(
"vspace", 0);
 
 1224    vspace = z ? atoi(z) : DFLT_VSPACE;
 
 1226    z = pTable->MarkupArg(
"hspace", 0);
 
 1230    if (HtmlTraceMask & HtmlTrace_Table4) {
 
 1233       if (vspace < 2) vspace = 2;
 
 1238    tbw = pTable->fBorderWidth;
 
 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) {
 
 1253       int align = pTable->fStyle.fAlign;
 
 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;
 
 1261    if (width == pTable->fMaxW[0]) {
 
 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;
 
 1267    } 
else if (width > pTable->fMaxW[0]) {
 
 1268       int *tmaxW = pTable->fMaxW;
 
 1269       double scale = ((double) width) / (double) tmaxW[0];
 
 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;
 
 1275    } 
else if (width > pTable->fMinW[0]) {
 
 1277       int *tminW = pTable->fMinW;
 
 1278       int *tmaxW = pTable->fMaxW;
 
 1279       scale = (double) (width - tminW[0]) / (double) (tmaxW[0] - tminW[0]);
 
 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);
 
 1301    SETMAX(fMaxX, pTable->fX + pTable->fW);
 
 1302    btm += tbw + cellSpacing;
 
 1305    for (i = 1; i <= n; i++) {
 
 1312    for (iRow = 1; iRow <= pTable->fNRow; iRow++) {
 
 1314       TRACE(HtmlTrace_Table2, (
"Row %d: btm=%d\n",iRow,btm));
 
 1318       while (p && p->fType != Html_TR) {
 
 1319          if (p->fType == Html_CAPTION) {
 
 1321             while (p && p != pEnd1 && p->fType != Html_EndCAPTION) p = p->fPNext;
 
 1325          TRACE(HtmlTrace_Table3, (
"Skipping token %s\n", fHtml->GetTokenName(p)));
 
 1327          if (p) p = p->fPNext;
 
 1332       defaultVAlign = p->GetVerticalAlignment(VAlign_Center);
 
 1335       for (iCol = 1; iCol <= pTable->fNCol && iCol <= HTML_MAX_COLUMNS; iCol++) {
 
 1336          if (lastRow[iCol] < iRow) ymax[iCol] = 0;
 
 1339       for (p = p->fPNext; p && p->fType != Html_TR && p != pEnd1; p = fPNext) {
 
 1342          TRACE(HtmlTrace_Table3, (
"Processing token %s\n", fHtml->GetTokenName(p)));
 
 1351                } 
while (iCol <= HTML_MAX_COLUMNS && lastRow[iCol] >= iRow);
 
 1353                TRACE(HtmlTrace_Table2,
 
 1354                      (
"Column %d: x=%d w=%d\n",iCol,x[iCol],w[iCol]));
 
 1358                if (iCol <= HTML_MAX_COLUMNS) {
 
 1359                   TGHtmlCell *cell = (TGHtmlCell *) p;
 
 1361                   fPNext = cell->fPEnd;
 
 1362                   if (cell->fRowspan == 0) {
 
 1363                      lastRow[iCol] = pTable->fNRow;
 
 1365                      lastRow[iCol] = iRow + cell->fRowspan - 1;
 
 1370                   valign[iCol] = p->GetVerticalAlignment(defaultVAlign);
 
 1373                   y[iCol] = btm + pad;
 
 1374                   cellContext.fHtml     = fHtml;
 
 1375                   cellContext.fPStart   = p->fPNext;
 
 1376                   cellContext.fPEnd     = fPNext;
 
 1377                   cellContext.fHeadRoom = 0;
 
 1378                   cellContext.fTop      = y[iCol];
 
 1379                   cellContext.fBottom   = y[iCol];
 
 1380                   cellContext.fLeft     = x[iCol];
 
 1381                   cellContext.fRight    = 0;
 
 1382                   cellContext.fPageWidth = x[iCol] + w[iCol];
 
 1383                   colspan = cell->fColspan;
 
 1386                           i <= pTable->fNCol && i <= HTML_MAX_COLUMNS; i++) {
 
 1387                         cellContext.fPageWidth += w[i] + separation;
 
 1388                         lastRow[i] = lastRow[iCol];
 
 1390                   } 
else if (colspan > 1) {
 
 1392                           i < iCol + colspan && i <= HTML_MAX_COLUMNS; i++) {
 
 1393                         cellContext.fPageWidth += w[i] + separation;
 
 1394                         lastRow[i] = lastRow[iCol];
 
 1397                   cellContext.fMaxX = 0;
 
 1398                   cellContext.fMaxY = 0;
 
 1399                   cellContext.fLeftMargin = 0;
 
 1400                   cellContext.fRightMargin = 0;
 
 1401                   cellContext.LayoutBlock();
 
 1402 #ifdef TABLE_TRIM_BLANK 
 1405                   if (HtmlLineWasBlank) {
 
 1406                      cellContext.fMaxY -= cellContext.headRoom;
 
 1408 #endif // TABLE_TRIM_BLANK 
 1409                   ymax[iCol] = cellContext.fMaxY;
 
 1410                   SETMAX(ymax[iCol], y[iCol]);
 
 1411                   cellContext.ClearMarginStack(&cellContext.fLeftMargin);
 
 1412                   cellContext.ClearMarginStack(&cellContext.fRightMargin);
 
 1415                   cell->fX = x[iCol] - pad;
 
 1417                   cell->fW = cellContext.fPageWidth + 2 * pad - x[iCol];
 
 1419                   TRACE(HtmlTrace_Table2,
 
 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) {
 
 1428                      iCol = HTML_MAX_COLUMNS + 1;
 
 1437             while (fPNext && fPNext != pEnd1 && fPNext->fType != Html_EndCAPTION) {
 
 1438                fPNext = fPNext->fPNext;
 
 1446       for (iCol = 1; iCol <= pTable->fNCol; iCol++) {
 
 1447          if (lastRow[iCol] == iRow || iRow == pTable->fNRow) {
 
 1448             SETMAX(rowBottom, ymax[iCol]);
 
 1452       TRACE(HtmlTrace_Table2, (
"Total row height: %d..%d -> %d\n",
 
 1453                              btm,rowBottom,rowBottom-btm));
 
 1456       for (iCol = 1; iCol <= pTable->fNCol; iCol++) {
 
 1458          TGHtmlCell *apCell = (TGHtmlCell *) apElem[iCol];
 
 1462          if (apElem[iCol] == 0 ||
 
 1463              (iRow != pTable->fNRow && lastRow[iCol] > iRow)) 
continue;
 
 1466             switch (valign[iCol]) {
 
 1467                case VAlign_Unknown:
 
 1469                   dy = (rowBottom - ymax[iCol])/2;
 
 1472             case VAlign_Baseline:
 
 1476                   dy = rowBottom - ymax[iCol];
 
 1480                TGHtmlElement *pLast = apCell->fPEnd;
 
 1482                TRACE(HtmlTrace_Table3, (
"Delta column %d by %d\n",iCol,dy));
 
 1484                fHtml->MoveVertically(apElem[iCol]->fPNext, pLast, dy);
 
 1488             apCell->fH = rowBottom + pad - apCell->fY;
 
 1493          btm = rowBottom + pad + cellSpacing;
 
 1497       pTable->fH = btm - pTable->fY;
 
 1499       fBottom = btm + vspace;
 
 1507       fHtml->ResetBlocks(); 
 
 1512       if (strcasecmp(zAlign, 
"left") == 0) {
 
 1513          savedContext.fMaxX = fMaxX;
 
 1514          savedContext.fMaxY = fMaxY;
 
 1515          *
this = savedContext;
 
 1516          PushMargin(&fLeftMargin, pTable->fW + 2, pTable->fY + pTable->fH + 2, 0);
 
 1517       } 
else if (strcasecmp(zAlign, 
"right") == 0) {
 
 1518          savedContext.fMaxX = fMaxX;
 
 1519          savedContext.fMaxY = fMaxY;
 
 1520          *
this = savedContext;
 
 1521          PushMargin(&fRightMargin, pTable->fW + 2, pTable->fY + pTable->fH + 2, 0);
 
 1526       TRACE(HtmlTrace_Table2, (
 
 1527             "Done with TableLayout().  x=%d y=%d w=%d h=%d Return %s\n",
 
 1528             pTable->fX, pTable->fY, pTable->fW, pTable->fH,
 
 1529             fHtml->GetTokenName(pEnd1)));
 
 1530       TRACE_POP(HtmlTrace_Table2);
 
 1542 void TGHtml::MoveVertically(TGHtmlElement *p, TGHtmlElement *pLast1, 
int dy)
 
 1544    if (dy == 0) 
return;
 
 1546    while (p && p != pLast1) {
 
 1549             ((TGHtmlAnchor *)p)->fY += dy;
 
 1553             ((TGHtmlTextElement *)p)->fY += dy;
 
 1557             ((TGHtmlLi *)p)->fY += dy;
 
 1562             ((TGHtmlCell *)p)->fY += dy;
 
 1566             ((TGHtmlTable *)p)->fY += dy;
 
 1570             ((TGHtmlImageMarkup *)p)->fY += dy;
 
 1578             ((TGHtmlInput *)p)->fY += dy;