⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 table.c

📁 将HTML转换为TXT文件的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ------------------------------------------------------------------------- *//* * 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 + -