📄 table.c
字号:
/* ------------------------------------------------------------------------- *//* * Copyright (c) 1999 * GMRS Software GmbH, Innsbrucker Ring 159, 81669 Munich, Germany. * http://www.gmrs.de * All rights reserved. * Author: Arno Unkrig (arno.unkrig@gmrs.de) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by GMRS Software GmbH. * 4. The name of GMRS Software GmbH may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY GMRS SOFTWARE GMBH ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GMRS SOFTWARE GMBH BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. *//* ------------------------------------------------------------------------- *//* * "Table::format()" has been taken out of "format.C" because it is way more * complex than the "format()" methods of the other HTML elements. *//* ------------------------------------------------------------------------- */#ident "$Id: table.C,v 1.15 1999/11/12 18:57:35 arno Exp $"#include "html.h"#include "auto_aptr.h"#include "format.h"/* ------------------------------------------------------------------------- */// Should be local to "Table::format()", but CFRONT can't handle this.struct LogicalCell { const TableCell *cell; // Points to the parsed cell.. int x, y; // Position of cell in table. int w, h; // COLSPAN/ROWSPAN of cell. int halign; int valign; Area::size_type width; // Current contents width. bool minimized; // Cannot be narrowed any more. auto_ptr<Area> area; // Formatted cell -- computed at a late stage.};/* ------------------------------------------------------------------------- *//* * Correct x and y of the logical cells according to the other cells' ROWSPAN * and COLSPAN. */static voidcorrect_xy( list<auto_ptr<LogicalCell> > *const lcs_in_out, int *const number_of_rows_in_out, int *const number_of_columns_in_out){ list<auto_ptr<LogicalCell> >::iterator i; for (i = lcs_in_out->begin(); i != lcs_in_out->end(); ++i) { const LogicalCell *const p = (*i).get(); if (p->w != 1 || p->h != 1) { list<auto_ptr<LogicalCell> >::iterator j; for (j = i, ++j; j != lcs_in_out->end(); ++j) { LogicalCell *const q = (*j).get(); if (q->y != p->y) break; q->x += p->w - 1; } for (; j != lcs_in_out->end(); ++j) { LogicalCell *const q = (*j).get(); if (q->y >= p->y + p->h) break; if (q->x >= p->x) q->x += p->w; } } if (p->x + p->w > *number_of_columns_in_out) *number_of_columns_in_out = p->x + p->w; if (p->y + p->h > *number_of_rows_in_out ) *number_of_rows_in_out = p->y + p->h; }}static voidcreate_lcs( const Table &t, const Area::size_type w, const Area::size_type left_border_width, const Area::size_type right_border_width, const Area::size_type column_spacing, list<auto_ptr<LogicalCell> > *const lcs_return, int *const number_of_rows_return, int *const number_of_columns_return){ *number_of_rows_return = 0; *number_of_columns_return = 0; const list<auto_ptr<TableRow> > &rl(*t.rows); list<auto_ptr<TableRow> >::const_iterator ri; int y; for (ri = rl.begin(), y = 0; ri != rl.end(); ++ri, ++y) { if (!(*ri).get()) continue; const TableRow &row(**ri); int row_halign = get_attribute( row.attributes.get(), "ALIGN", Area::LEFT, "LEFT", Area::LEFT, "CENTER", Area::CENTER, "RIGHT", Area::RIGHT, 0 ); int row_valign = get_attribute( row.attributes.get(), "VALIGN", Area::MIDDLE, "TOP", Area::LEFT, "MIDDLE", Area::MIDDLE, "BOTTOM", Area::BOTTOM, 0 ); const list<auto_ptr<TableCell> > &cl(*row.cells); list<auto_ptr<TableCell> >::const_iterator ci; int x; for (ci = cl.begin(), x = 0; ci != cl.end(); ++ci, ++x) { if (!(*ci).get()) continue; const TableCell &cell(**ci); auto_ptr<LogicalCell> p(new LogicalCell); p->cell = &cell; p->x = x; p->y = y; p->w = get_attribute(cell.attributes.get(), "COLSPAN", 1); p->h = get_attribute(cell.attributes.get(), "ROWSPAN", 1); if (p->w < 1) p->w = 1; if (p->h < 1) p->h = 1; if (x + p->w > *number_of_columns_return) { *number_of_columns_return = x + p->w; } if (y + p->h > *number_of_rows_return) { *number_of_rows_return = y + p->h; } p->halign = get_attribute( cell.attributes.get(), "ALIGN", row_halign, "LEFT", Area::LEFT, "CENTER", Area::CENTER, "RIGHT", Area::RIGHT, 0 ); p->valign = get_attribute( cell.attributes.get(), "VALIGN", row_valign, "TOP", Area::TOP, "MIDDLE", Area::MIDDLE, "BOTTOM", Area::BOTTOM, 0 ); { auto_ptr<Area> tmp(cell.format( w - left_border_width - right_border_width - (*number_of_columns_return - 1) * (column_spacing + 0), Area::LEFT // Yields better results than "p->halign"! )); p->width = tmp.get() ? tmp->width() : 0; } p->minimized = false; lcs_return->push_back(p); } } correct_xy(lcs_return, number_of_rows_return, number_of_columns_return);}static voidcompute_widths( const list<auto_ptr<LogicalCell> > &lcs, const int number_of_columns, const Area::size_type column_spacing, const Area::size_type left_border_width, const Area::size_type right_border_width, Area::size_type *const table_width_return, Area::size_type *const column_widths_return){ /* * Compute the column widths. */ { for (int i = 0; i < number_of_columns; i++) column_widths_return[i] = 0; } for (int x = 0; x < number_of_columns; x++) { list<auto_ptr<LogicalCell> >::const_iterator i; for (i = lcs.begin(); i != lcs.end(); ++i) { const LogicalCell &lc(**i); if (x != lc.x + lc.w - 1) continue; // Cell not in column? Area::size_type width = lc.width; for (int j = lc.x; j < x; j++) { // Beware! "width" is unsigned! if (column_widths_return[j] + column_spacing >= width) { width = 0; } else { width -= column_widths_return[j] + column_spacing; } } if (width >= column_widths_return[x]) column_widths_return[x] = width; } } /* * Compute the table width. */ *table_width_return = ( left_border_width + (number_of_columns - 1) * column_spacing + right_border_width ); { for (int x = 0; x < number_of_columns; x++) { *table_width_return += column_widths_return[x]; } }}/* * Examine the table for the widest column that can be narrowed. (A column * cannot be narrowed if its widest cell cannot be narrowed.) Return "false" * if none of the columns can be narrowed. Otherwise, attempt to narrow that * column and update "lcs_in_out", "column_widths_in_out", and * "table_width_in_out". */static boolnarrow_table( list<auto_ptr<LogicalCell> > *const lcs_in_out, const int number_of_columns, const Area::size_type column_spacing, Area::size_type *const column_widths_in_out, Area::size_type *const table_width_in_out){ /* * Seek for the widest column that can still be narrowed. */ int widest_column = -1; for (int x = 0; x < number_of_columns; x++) { // Zero width columns cannot be narrowed. if (column_widths_in_out[x] == 0) continue; // Is this the widest column so far? if ( widest_column != -1 && column_widths_in_out[x] <= column_widths_in_out[widest_column] ) continue; // Yes; can the widest cell(s) in this column be narrowed? const list<auto_ptr<LogicalCell> > &lcl(*lcs_in_out); list<auto_ptr<LogicalCell> >::const_iterator i; for (i = lcl.begin(); i != lcl.end(); ++i) { const LogicalCell &lc = **i; if (lc.x + lc.w - 1 != x) continue; // Not in this column. if (!lc.minimized) continue; Area::size_type left_of_cell = 0; for (int j = lc.x; j < x; j++) { left_of_cell += column_widths_in_out[j] + column_spacing; } if (lc.width >= left_of_cell + column_widths_in_out[x]) { // Minimized cell is as wide as the column; cannot narrow this // column. break; } } if (i == lcl.end()) widest_column = x; } /* * Give up if there is no more cell that can be narrowed. */ if (widest_column == -1) return false; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -