// -*- C++ -*- /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp * * html-table.h * * provides the methods necessary to handle indentation and tab * positions using html tables. */ /* This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "driver.h" #include "stringclass.h" #include "cset.h" #include "html-table.h" #include "ctype.h" #include "html.h" #if !defined(TRUE) # define TRUE (1==1) #endif #if !defined(FALSE) # define FALSE (1==0) #endif tabs::tabs () : tab(NULL) { } tabs::~tabs () { delete_list(); } /* * delete_list - frees the tab list and sets tab to NULL. */ void tabs::delete_list (void) { tab_position *p = tab; tab_position *q; while (p != NULL) { q = p; p = p->next; free(q); } tab = NULL; } void tabs::clear (void) { delete_list(); } /* * compatible - returns TRUE if the tab stops in, s, do * not conflict with the current tab stops. * The new tab stops are _not_ placed into * this class. */ int tabs::compatible (const char *s) { char align; int total=0; tab_position *last = tab; if (last == NULL) return FALSE; // no tab stops defined // move over tag name while ((*s != (char)0) && !isspace(*s)) s++; while (*s != (char)0 && last != NULL) { // move over white space while ((*s != (char)0) && isspace(*s)) s++; // collect alignment align = *s; // move over alignment s++; // move over white space while ((*s != (char)0) && isspace(*s)) s++; // collect tab position total = atoi(s); // move over tab position while ((*s != (char)0) && !isspace(*s)) s++; if (last->alignment != align || last->position != total) return FALSE; last = last->next; } return TRUE; } /* * init - scans the string, s, and initializes the tab stops. */ void tabs::init (const char *s) { char align; int total=0; tab_position *last = NULL; clear(); // remove any tab stops // move over tag name while ((*s != (char)0) && !isspace(*s)) s++; while (*s != (char)0) { // move over white space while ((*s != (char)0) && isspace(*s)) s++; // collect alignment align = *s; // move over alignment s++; // move over white space while ((*s != (char)0) && isspace(*s)) s++; // collect tab position total = atoi(s); // move over tab position while ((*s != (char)0) && !isspace(*s)) s++; if (last == NULL) { tab = (tab_position *)malloc(sizeof(tab_position)); last = tab; } else { last->next = (tab_position *)malloc(sizeof(tab_position)); last = last->next; } last->alignment = align; last->position = total; last->next = NULL; } } /* * check_init - define tab stops using, s, providing none already exist. */ void tabs::check_init (const char *s) { if (tab == NULL) init(s); } /* * find_tab - returns the tab number corresponding to the position, pos. */ int tabs::find_tab (int pos) { tab_position *p; int i=0; for (p = tab; p != NULL; p = p->next) { i++; if (p->position == pos) return i; } return 0; } /* * get_tab_pos - returns the, nth, tab position */ int tabs::get_tab_pos (int n) { tab_position *p; n--; for (p = tab; (p != NULL) && (n>0); p = p->next) { n--; if (n == 0) return p->position; } return 0; } char tabs::get_tab_align (int n) { tab_position *p; n--; for (p = tab; (p != NULL) && (n>0); p = p->next) { n--; if (n == 0) return p->alignment; } return 'L'; } /* * dump_tab - display tab positions */ void tabs::dump_tabs (void) { int i=1; tab_position *p; for (p = tab; p != NULL; p = p->next) { printf("tab %d is %d\n", i, p->position); i++; } } /* * html_table - methods */ html_table::html_table (simple_output *op, int linelen) : columns(NULL), out(op), linelength(linelen), last_col(NULL), start_space(FALSE) { tab_stops = new tabs(); } html_table::~html_table () { cols *c; if (tab_stops != NULL) delete tab_stops; c = columns; while (columns != NULL) { columns = columns->next; free(c); c = columns; } } /* * remove_cols - remove a list of columns as defined by, c. */ void html_table::remove_cols (cols *c) { cols *p; while (c != NULL) { p = c; c = c->next; free(p); } } /* * set_linelength - sets the line length value in this table. * It also adds an extra blank column to the * table should linelen exceed the last column. */ void html_table::set_linelength (int linelen) { cols *p = NULL; cols *c; linelength = linelen; for (c = columns; c != NULL; c = c->next) { if (c->right > linelength) { c->right = linelength; remove_cols(c->next); c->next = NULL; return; } p = c; } if (p != NULL && p->right > 0) add_column(p->no+1, p->right, linelength, 'L'); } /* * get_effective_linelength - */ int html_table::get_effective_linelength (void) { if (columns != NULL) return linelength - columns->left; else return linelength; } /* * add_indent - adds the indent to a table. */ void html_table::add_indent (int indent) { if (columns != NULL && columns->left > indent) add_column(0, indent, columns->left, 'L'); } /* * emit_table_header - emits the html header for this table. */ void html_table::emit_table_header (int space) { if (columns == NULL) return; // dump_table(); last_col = NULL; if (linelength > 0) { out->nl(); out->nl(); #if 0 if (space) out->put_string("
"); #endif start_space = space; out->put_string("
") .nl(); b = b->next; } // move across to column n while (b != c) { // we compute the difference after converting positions // to avoid rounding errors width = (get_right(b)*100 + get_effective_linelength()/2) / get_effective_linelength() - (b->left*100 + get_effective_linelength()/2) /get_effective_linelength(); if (width) out->put_string(" | ") .nl(); // have we a gap? if (is_gap(b)) out->put_string(" | ") .nl(); b = b->next; } width = (get_right(b)*100 + get_effective_linelength()/2) / get_effective_linelength() - (b->left*100 + get_effective_linelength()/2) /get_effective_linelength(); switch (b->alignment) { case 'C': out->put_string(" | ") .nl(); break; case 'R': out->put_string(" | ") .nl(); break; default: out->put_string(" | ") .nl(); } // remember column, b last_col = b; } } /* * finish_row - */ void html_table::finish_row (void) { int n = 0; cols *c; if (last_col != NULL) { for (c = last_col->next; c != NULL; c = c->next) n = c->no; if (n > 0) emit_col(n); out->put_string(" | ").nl(); } } /* * emit_new_row - move to the next row. */ void html_table::emit_new_row (void) { finish_row(); out->put_string("