6 int w; // Actual width for current rendering
13 void ComputeTable(Surface surface, Block table, int textPos, int * width, int * height, int maxW, int maxH, RenderFlags flags, int sy, int sx)
15 if(flags.minW || flags.lineW || flags.width)
23 // Pass 1: Figure out column widths
25 for(column = table.columns.first; column; column = column.next)
38 // Temporary variable:
42 for(row = table.subBlocks.first; row && row.type != TABLE; )
47 column = table.columns.first;
48 for(cell = row.subBlocks.first; cell; cell = cell.next)
54 int minW = 0, lineW = 0;
57 // Disconnect the cell
58 Block parent = cell.parent;
59 Block next = cell.next;
63 while(column && column.rowSpan)
68 column = Column { rowSpan = cell.rowSpan };
69 // if(cell.rowSpan) Do proper thing if 0 rowSpan
71 table.columns.Add(column);
75 block = cell.subBlocks.first;
82 // Minimum width for this column
87 ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &w, MAXINT, 0, RenderFlags { lineW = true }, 0, null, null, null, true, sy, sx);
89 w = Max(maxW * cell.pWidth / 100, w);*/
92 ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &w, 0, 0, flags, 0, null, null, null, true, sy, sx);
94 // Width specified absolute is minimum width
97 w = Max(cell.width, w);
104 // Width specified absolute will not extend
105 if(maxW < cell.minW || cell.width)
108 lineW = Max(cell.minW, cell.width);
113 ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &w, maxW, 0, RenderFlags { lineW = true }, 0, null, null, null, true, sy, sx);
115 w = Max(maxW * cell.pWidth / 100, w);
116 lineW = Max(lineW, w);
120 textPos = nextCellPos;
121 block = nextCellBlock;
124 cell.parent = parent;
127 minW += table.cellPadding * 2;
128 lineW += table.cellPadding * 2;
135 // First only process non spanning cells
140 column.width = Max(column.width, cell.width);
141 column.minW = Max(column.minW, cell.minW);
145 column.lineW = Max(column.lineW, cell.lineW);
146 column.minW = Max(column.minW, cell.minW);
150 for(c = 0; c<cell.span && column; c++)
151 column = column.next;
155 for(column = table.columns.first; column; column = column.next)
159 row = NextBlockUp(surface, row, null, 0);
162 row = NextBlock(surface, row, null, 0);
165 // Start with bare minimum
168 for(column = table.columns.first; column; column = column.next)
170 column.w = column.minW;
178 if(flags.lineW /*&& flags.width*/)
180 // Expand using lineW
181 if(!table.pWidth && !table.width)
185 for(column = table.columns.first; column; column = column.next)
187 for(row = table.subBlocks.first; row && row.type != TABLE; )
194 column = table.columns.first;
196 for(cell = row.subBlocks.first; cell; cell = cell.next)
201 while(column && column.rowSpan)
202 column = column.next;
204 for(c = 0; c<cell.span && column; c++)
206 column.rowSpan = cell.rowSpan;
208 column = column.next;
210 rowLineW += Max(sumColW, cell.lineW);
212 totalLineW = Max(totalLineW, rowLineW);
213 row = NextBlockUp(surface, row, null, 0);
216 row = NextBlock(surface, row, null, 0);
218 // MOVED THIS UP HERE
219 for(column = table.columns.first; column; column = column.next)
220 if(column.rowSpan) column.rowSpan--;
223 totalLineW = Min(maxW, totalLineW);
224 table.w = Max(table.w, totalLineW);
226 for(column = table.columns.first; column; column = column.next)
227 if(column.rowSpan) column.rowSpan--;
232 // Expand table more (only expand absolute if we're in that pass)
233 if(table.pWidth && (flags.width))
235 table.w = Max(table.w, maxW * table.pWidth / 100);
239 table.w = Max(table.w, table.width);
242 // Repartition the rest of the space in the columns according to column.lineW
247 // Step 1: Weights how to distribute
248 for(column = table.columns.first; column; column = column.next)
253 for(row = table.subBlocks.first; row && row.type != TABLE; )
258 Column columnStart = table.columns.first;
260 for(cell = row.subBlocks.first; cell; cell = cell.next)
265 while(columnStart && columnStart.rowSpan)
266 columnStart = columnStart.next;
268 for(c = 0, column = columnStart; c<cell.span && column; c++)
270 column.rowSpan = cell.rowSpan;
273 column = column.next;
275 if(cell.span == 1 && totalW < cell.lineW)
277 for(c = 0, column = columnStart; c<cell.span && column; c++, column = column.next)
279 int desire = cell.lineW - totalW;
280 column.desire += desire / cell.span;
282 needed += cell.lineW - totalW;
285 columnStart = column;
287 for(column = table.columns.first; column; column = column.next)
288 if(column.rowSpan) column.rowSpan--;
289 row = NextBlockUp(surface, row, null, 0);
292 row = NextBlock(surface, row, null, 0);
295 // Take care of spanning across columns (minw)
296 for(column = table.columns.first; column; column = column.next)
299 for(row = table.subBlocks.first; row && row.type != TABLE; )
304 Column columnStart = table.columns.first;
306 for(cell = row.subBlocks.first; cell; cell = cell.next)
312 while(columnStart && columnStart.rowSpan)
313 columnStart = columnStart.next;
315 for(c = 0, column = columnStart; c<cell.span && column; c++)
317 column.rowSpan = cell.rowSpan;
319 sumDesires += column.desire;
320 column = column.next;
322 if(cell.span > 1 && totalW < cell.minW)
324 for(c = 0, column = columnStart; c<cell.span && column; c++)
328 int given = (column.desire) * (cell.minW - totalW) / sumDesires;
329 column.minW += given;
331 column = column.next;
334 // Check if we've got enough now...
336 for(c = 0, column = columnStart; c<cell.span && column; c++)
338 totalW += column.minW;
339 column = column.next;
342 if(totalW < cell.minW)
344 for(c = 0, column = columnStart; c<cell.span && column; c++)
346 column.minW = Max(column.minW, (cell.minW - totalW) / cell.span);
347 column = column.next;
351 columnStart = column;
353 for(column = table.columns.first; column; column = column.next)
354 if(column.rowSpan) column.rowSpan--;
355 row = NextBlockUp(surface, row, null, 0);
358 row = NextBlock(surface, row, null, 0);
361 for(column = table.columns.first; column; column = column.next)
363 if(column.minW > column.w)
365 w += column.minW - column.w;
366 column.w = column.minW;
371 // Repeat Step 1: Weights how to distribute
373 for(column = table.columns.first; column; column = column.next)
378 for(row = table.subBlocks.first; row && row.type != TABLE; )
383 Column columnStart = table.columns.first;
385 for(cell = row.subBlocks.first; cell; cell = cell.next)
390 while(columnStart && columnStart.rowSpan)
391 columnStart = columnStart.next;
393 for(c = 0, column = columnStart; c<cell.span && column; c++)
395 column.rowSpan = cell.rowSpan;
396 if(/*cell.span == 1 && */cell.width)
398 column = column.next;
400 if(/*cell.span == 1 && */totalW < cell.lineW && cell.width)
402 for(c = 0, column = columnStart; c<cell.span && column; c++, column = column.next)
404 int desire = cell.lineW - totalW;
405 column.desire += desire / cell.span;
407 needed += cell.lineW - totalW;
410 columnStart = column;
412 for(column = table.columns.first; column; column = column.next)
413 if(column.rowSpan) column.rowSpan--;
414 row = NextBlockUp(surface, row, null, 0);
417 row = NextBlock(surface, row, null, 0);
420 // Step 2: Do the distribution
423 for(column = table.columns.first; column; column = column.next)
427 int give = (column.desire) * (table.w - w) / needed;
428 give = Min(give, column.width - column.w);
435 for(column = table.columns.first; column; column = column.next)
441 // Repease Step 1: Weights how to distribute
443 for(column = table.columns.first; column; column = column.next)
448 for(row = table.subBlocks.first; row && row.type != TABLE; )
453 Column columnStart = table.columns.first;
455 for(cell = row.subBlocks.first; cell; cell = cell.next)
460 while(columnStart && columnStart.rowSpan)
461 columnStart = columnStart.next;
463 for(c = 0, column = columnStart; c<cell.span && column; c++)
465 column.rowSpan = cell.rowSpan;
466 if(/*cell.span == 1 && */!cell.width)
468 column = column.next;
470 if(/*cell.span == 1 && */totalW < cell.lineW && !cell.width)
472 for(c = 0, column = columnStart; c<cell.span && column; c++, column = column.next)
474 int desire = cell.lineW - totalW;
475 column.desire += desire / cell.span;
477 needed += cell.lineW - totalW;
480 columnStart = column;
482 for(column = table.columns.first; column; column = column.next)
483 if(column.rowSpan) column.rowSpan--;
484 row = NextBlockUp(surface, row, null, 0);
487 row = NextBlock(surface, row, null, 0);
490 // Step 2: Do the distribution
493 for(column = table.columns.first; column; column = column.next)
497 int give = (column.desire) * (table.w - w) / needed;
504 for(column = table.columns.first; column; column = column.next)
508 // Repartition the rest of the space in the columns
513 for(column = table.columns.first; column; column = column.next)
518 totalLineW += column.lineW;
523 for(column = table.columns.first; column; column = column.next)
529 give = (table.w - w) * column.lineW / totalLineW;
531 give = (table.w - w) / numNotFixed;
538 for(column = table.columns.first; column; column = column.next)
539 totalLineW += column.lineW;
540 for(column = table.columns.first; column; column = column.next)
544 give = (table.w - w) * column.lineW / totalLineW;
546 give = (table.w - w) / table.columns.count;
551 for(column = table.columns.first; column; column = column.next)
557 /*switch(table.halign)
560 startX = Max(left, (left + right - table.w)/2);
562 case HorizontalAlignment::right:
563 startX = Max(left, right - table.w);
568 // Pass 2: Figure out heights
570 for(column = table.columns.first; column; column = column.next)
572 for(row = table.subBlocks.first; row && row.type != TABLE; )
577 OldList leftObjects { };
578 OldList rightObjects { };
582 column = table.columns.first;
586 for(cell = row.subBlocks.first; cell; cell = cell.next)
594 int cellMaxH = row.h;
597 AlignedObject object, nextObject;
599 // Disconnect the cell
600 Block parent = cell.parent;
601 Block next = cell.next;
608 column = column.next;
609 // TOCHECK: Added column null check here..
610 if(column && cell.rowSpan)
611 column.rowSpan = cell.rowSpan;
615 for(c = 0; (!cell.span || c<cell.span) && column; c++)
618 column = column.next;
623 block = cell.subBlocks.first;
632 for(object = leftObjects.last; object; object = nextObject)
634 nextObject = object.prev;
635 if(y < object.untilY || object.next)
638 leftObjects.Delete(object);
640 for(object = rightObjects.last; object; object = nextObject)
642 nextObject = object.prev;
643 if(y < object.untilY || object.next)
646 rightObjects.Delete(object);
648 cellW = Max(cellW, 0);
650 // TRIED ADDING THIS CODE HERE...
654 // Compute aligned objects
655 left = sx + table.cellPadding; // Add cell border/margins here?
656 right = sx + cellW - table.cellPadding; // Subtract cell border/margins here?
658 for(object = leftObjects.last; object; object = nextObject)
660 nextObject = object.prev;
661 if(y < object.untilY || object.next)
664 leftObjects.Delete(object);
666 for(object = rightObjects.last; object; object = nextObject)
668 nextObject = object.prev;
669 if(y < object.untilY || object.next)
672 rightObjects.Delete(object);
674 right = Max(left, right);
676 if(cell.halign == middle /*|| thisLineCentered*/)
678 x = (left + right - lineW)/2;
681 else if(cell.halign == HorizontalAlignment::right)
689 newLineH = ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &lineW, right - left /*cellW*/, cellMaxH, flags, y, &leftObjects, &rightObjects, &changeLine, true, sy, x);
691 textPos = nextCellPos;
692 block = nextCellBlock;
694 lineH = Max(lineH, newLineH);
702 cellMaxH -= newLineH;
707 for(object = leftObjects.last; object; object = nextObject)
709 nextObject = object.prev;
710 y = Max(y, object.untilY);
711 leftObjects.Delete(object);
713 for(object = rightObjects.last; object; object = nextObject)
715 nextObject = object.prev;
716 y = Max(y, object.untilY);
717 rightObjects.Delete(object);
725 cell.parent = parent;
728 row.height = Max(row.height, cell.height);
730 cell.h = Max(cell.h, cell.height);
732 row.h = Max(row.h, cell.h);
735 // row.h = Max(row.h, row.height);
739 for(column = table.columns.first; column; column = column.next)
744 row = NextBlockUp(surface, row, null, 0);
747 row = NextBlock(surface, row, null, 0);
751 table.h = maxH * table.pHeight / 100;
752 else if(table.height)
753 table.h = table.height;
765 // Repartition the rest of the space in the rows
766 for(row = table.subBlocks.first; row && row.type != TABLE; )
772 row = NextBlockUp(surface, row, null, 0);
775 row = NextBlock(surface, row, null, 0);
779 for(row = table.subBlocks.first; row && row.type != TABLE; )
783 row.h += (table.h - h) / numNotFixed;
784 row = NextBlockUp(surface, row, null, 0);
787 row = NextBlock(surface, row, null, 0);
798 static void RenderCell(HTMLView browser, Surface surface, Block cell, int cellX, int y)
803 Block row = cell.parent;
808 AlignedObject object, nextObject;
809 OldList leftObjects { };
810 OldList rightObjects { };
813 // Disconnect the cell
814 Block parent = cell.parent;
815 Block next = cell.next;
817 while(table && table.type != TABLE) table = table.parent;
829 ColorAlpha fg = surface.GetForeground();
830 surface.SetForeground(white);
832 // surface.Stretch(cell.bitmap, x,y,0,0,cell.w,cell.h,cell.bitmap.width, cell.bitmap.height);
833 surface.Tile(cell.bitmap, cellX,y,cellW,row.h);
835 surface.SetForeground(fg);
837 else if(cell.bgColor)
839 surface.SetBackground(cell.bgColor);
840 surface.Area(cellX, y, cellX+cellW-1, y+row.h-1);
843 //surface.SetForeground(Color { 85,85,255 });
844 //surface.Rectangle(cellX, y, cellX+cellW-1, y+row.h-1);
846 if(cell.valign == middle)
848 y += (row.h - cell.h) / 2;
850 else if(cell.valign == bottom)
854 browser.isSelected = false;
857 while(block && table)
862 int thisLineCentered = centered;
868 // Compute aligned objects
869 left = cellX + table.cellPadding; // Add cell border/margins here?
870 right = cellX + cellW - table.cellPadding; // Subtract cell border/margins here?
872 for(object = leftObjects.last; object; object = nextObject)
874 nextObject = object.prev;
875 if(y < object.untilY || object.next)
878 leftObjects.Delete(object);
880 for(object = rightObjects.last; object; object = nextObject)
882 nextObject = object.prev;
883 if(y < object.untilY || object.next)
886 rightObjects.Delete(object);
888 right = Max(left, right);
892 newLineH = ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &lineW, maxW, maxH, RenderFlags {}, y, &leftObjects, &rightObjects, &changeLine, false, 0, 0);
895 if(cell.halign == middle || thisLineCentered)
897 x = (left + right - lineW)/2;
900 else if(cell.halign == HorizontalAlignment::right)
908 lineH = Max(lineH, newLineH);
910 RenderLine(browser, surface, x, y, cellW, newLineH, block, textPos, nextCellBlock, nextCellPos, left, right);
920 textPos = nextCellPos;
921 block = nextCellBlock;
925 for(object = leftObjects.last; object; object = nextObject)
927 nextObject = object.prev;
928 y = Max(y, object.untilY);
929 leftObjects.Delete(object);
931 for(object = rightObjects.last; object; object = nextObject)
933 nextObject = object.prev;
934 y = Max(y, object.untilY);
935 rightObjects.Delete(object);
938 cell.parent = parent;
943 static void RenderRow(HTMLView browser, Surface surface, Block row, Block table, int x, int y)
947 Column column = table.columns.first;
948 for(cell = row.subBlocks.first; cell; cell = cell.next)
954 while(column && column.rowSpan)
955 column = column.next;
957 RenderCell(browser, surface, cell, x, y);
959 for(c = 0; c<cell.span && column; c++)
961 column.rowSpan = cell.rowSpan;
963 column = column.next;
970 void RenderTable(HTMLView browser, Surface surface, int x, int y, int w, int h, int left, int right, Block table)
978 x = Max(left, (left + right - table.w)/2);
980 case HorizontalAlignment::right:
981 x = Max(left, right - table.w);
987 ColorAlpha fg = surface.GetForeground();
988 surface.SetForeground(white);
990 // surface.Stretch(table.bitmap, x,y,0,0,table.w,table.h,table.bitmap.width, table.bitmap.height);
991 surface.Tile(table.bitmap, x,y,table.w,table.h);
993 surface.SetForeground(fg);
995 else if(table.bgColor)
997 surface.SetBackground(table.bgColor);
998 surface.Area(x,y,x+table.w-1,y+table.h-1);
1001 for(column = table.columns.first; column; column = column.next)
1004 for(row = table.subBlocks.first; row && row.type != TABLE; )
1008 RenderRow(browser, surface, row, table, x, y);
1010 for(column = table.columns.first; column; column = column.next)
1015 row = NextBlockUp(surface, row, null, 0);
1018 row = NextBlock(surface, row, null, 0);
1023 static bool PickCell(HTMLView browser, Surface surface, Block cell, int cellX, int y,
1024 int pickX, int pickY, Block* pickBlock, int * pickTextPos)
1026 bool result = false;
1030 Block row = cell.parent;
1035 AlignedObject object, nextObject;
1036 OldList leftObjects { };
1037 OldList rightObjects { };
1039 // Disconnect the cell
1040 Block parent = cell.parent;
1041 Block next = cell.next;
1044 while(table && table.type != TABLE) table = table.parent;
1049 if(cell.valign == middle)
1051 y += (row.h - cell.h) / 2;
1053 else if(cell.valign == bottom)
1055 y += row.h - cell.h;
1058 // Render whole cell
1059 for(;block && table && !result;)
1061 int lineW, newLineH;
1062 Block nextCellBlock;
1064 int thisLineCentered = centered;
1071 // Compute aligned objects
1072 left = cellX + table.cellPadding; // Add cell border/margins here?
1073 right = cellX + cellW - table.cellPadding; // Subtract cell border/margins here?
1075 for(object = leftObjects.last; object; object = nextObject)
1077 nextObject = object.prev;
1078 if(y < object.untilY || object.next)
1081 leftObjects.Delete(object);
1083 for(object = rightObjects.last; object; object = nextObject)
1085 nextObject = object.prev;
1086 if(y < object.untilY || object.next)
1089 rightObjects.Delete(object);
1091 right = Max(left, right);
1092 maxW = right - left;
1094 font = surface.font;
1095 newLineH = ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &lineW, maxW, maxH, RenderFlags {}, y, &leftObjects, &rightObjects, &changeLine, false, 0, 0);
1096 surface.font = font;
1098 //surface.TextFont(font);
1100 if(cell.halign == middle || thisLineCentered)
1102 x = (left + right - lineW)/2;
1105 else if(cell.halign == HorizontalAlignment::right)
1113 lineH = Max(lineH, newLineH);
1115 result = PickLine(browser, surface, x, y, cellW, newLineH, block, textPos, nextCellBlock, nextCellPos, left, right, pickX, pickY, pickBlock, pickTextPos);
1125 textPos = nextCellPos;
1126 block = nextCellBlock;
1130 for(object = leftObjects.last; object; object = nextObject)
1132 nextObject = object.prev;
1133 y = Max(y, object.untilY);
1134 leftObjects.Delete(object);
1136 for(object = rightObjects.last; object; object = nextObject)
1138 nextObject = object.prev;
1139 y = Max(y, object.untilY);
1140 rightObjects.Delete(object);
1143 cell.parent = parent;
1149 static bool PickRow(HTMLView browser, Surface surface, Block row, Block table, int x, int y,
1150 int pickX, int pickY, Block* pickBlock, int * pickTextPos)
1152 bool result = false;
1155 Column column = table.columns.first;
1156 for(cell = row.subBlocks.first; cell; cell = cell.next)
1162 while(column && column.rowSpan)
1163 column = column.next;
1165 result = PickCell(browser, surface, cell, x, y, pickX, pickY, pickBlock, pickTextPos);
1169 for(c = 0; c<cell.span && column; c++)
1171 column.rowSpan = cell.rowSpan;
1173 column = column.next;
1181 bool PickTable(HTMLView browser, Surface surface, int x, int y, int w, int h, int left, int right, Block table,
1182 int pickX, int pickY, Block* pickBlock, int * pickTextPos)
1184 bool result = false;
1188 switch(table.halign)
1191 x = Max(left, (left + right - table.w)/2);
1193 case HorizontalAlignment::right:
1194 x = Max(left, right - table.w);
1198 for(column = table.columns.first; column; column = column.next)
1201 for(row = table.subBlocks.first; row && row.type != TABLE; )
1205 result = PickRow(browser, surface, row, table, x, y, pickX, pickY, pickBlock, pickTextPos);
1207 for(column = table.columns.first; column; column = column.next)
1214 row = NextBlockUp(surface, row, null, 0);
1217 row = NextBlock(surface, row, null, 0);
1222 static void PositionCell(HTMLView browser, Surface surface, Block cell, int cellX, int y)
1227 Block row = cell.parent;
1232 AlignedObject object, nextObject;
1233 OldList leftObjects { };
1234 OldList rightObjects { };
1236 // Disconnect the cell
1237 Block parent = cell.parent;
1238 Block next = cell.next;
1242 while(table && table.type != TABLE) table = table.parent;
1246 if(cell.valign == middle)
1248 y += (row.h - cell.h) / 2;
1250 else if(cell.valign == bottom)
1252 y += row.h - cell.h;
1255 // Render whole cell
1256 for(;block && table;)
1258 int lineW, newLineH;
1259 Block nextCellBlock;
1261 int thisLineCentered = centered;
1268 // Compute aligned objects
1269 left = cellX + table.cellPadding; // Add cell border/margins here?
1270 right = cellX + cellW - table.cellPadding; // Subtract cell border/margins here?
1272 for(object = leftObjects.last; object; object = nextObject)
1274 nextObject = object.prev;
1275 if(y < object.untilY || object.next)
1278 leftObjects.Delete(object);
1280 for(object = rightObjects.last; object; object = nextObject)
1282 nextObject = object.prev;
1283 if(y < object.untilY || object.next)
1286 rightObjects.Delete(object);
1288 right = Max(left, right);
1289 maxW = right - left;
1291 font = surface.font;
1292 newLineH = ComputeLine(surface, block, textPos, &nextCellBlock, &nextCellPos, ¢ered, &lineW, maxW, maxH, RenderFlags {}, y, &leftObjects, &rightObjects, &changeLine, false, 0, 0);
1293 surface.font = font;
1295 // surface.TextFont(font);
1297 if(cell.halign == middle || thisLineCentered)
1299 x = (left + right - lineW)/2;
1302 else if(cell.halign == HorizontalAlignment::right)
1310 lineH = Max(lineH, newLineH);
1312 PositionLine(browser, surface, x, y, cellW, newLineH, block, textPos, nextCellBlock, nextCellPos, left, right);
1322 textPos = nextCellPos;
1323 block = nextCellBlock;
1327 for(object = leftObjects.last; object; object = nextObject)
1329 nextObject = object.prev;
1330 y = Max(y, object.untilY);
1331 leftObjects.Delete(object);
1333 for(object = rightObjects.last; object; object = nextObject)
1335 nextObject = object.prev;
1336 y = Max(y, object.untilY);
1337 rightObjects.Delete(object);
1340 cell.parent = parent;
1345 static void PositionRow(HTMLView browser, Surface surface, Block row, Block table, int x, int y)
1349 Column column = table.columns.first;
1350 for(cell = row.subBlocks.first; cell; cell = cell.next)
1356 while(column && column.rowSpan)
1357 column = column.next;
1359 PositionCell(browser, surface, cell, x, y);
1361 for(c = 0; c<cell.span && column; c++)
1363 column.rowSpan = cell.rowSpan;
1365 column = column.next;
1372 void PositionTable(HTMLView browser, Surface surface, int x, int y, int w, int h, int left, int right, Block table)
1377 switch(table.halign)
1380 x = Max(left, (left + right - table.w)/2);
1382 case HorizontalAlignment::right:
1383 x = Max(left, right - table.w);
1387 for(column = table.columns.first; column; column = column.next)
1390 for(row = table.subBlocks.first; row && row.type != TABLE; )
1394 PositionRow(browser, surface, row, table, x, y);
1396 for(column = table.columns.first; column; column = column.next)
1401 row = NextBlockUp(surface, row, null, 0);
1404 row = NextBlock(surface, row, null, 0);