#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();
}
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();
}
int tabs::compatible (const char *s)
{
char align;
int total=0;
tab_position *last = tab;
if (last == NULL)
return FALSE;
while ((*s != (char)0) && !isspace(*s))
s++;
while (*s != (char)0 && last != NULL) {
while ((*s != (char)0) && isspace(*s))
s++;
align = *s;
s++;
while ((*s != (char)0) && isspace(*s))
s++;
total += atoi(s);
while ((*s != (char)0) && !isspace(*s))
s++;
if (last->alignment != align || last->position != total)
return FALSE;
last = last->next;
}
return TRUE;
}
void tabs::init (const char *s)
{
char align;
int total=0;
tab_position *last = NULL;
clear();
while ((*s != (char)0) && !isspace(*s))
s++;
while (*s != (char)0) {
while ((*s != (char)0) && isspace(*s))
s++;
align = *s;
s++;
while ((*s != (char)0) && isspace(*s))
s++;
total = atoi(s);
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;
}
}
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;
}
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';
}
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::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 ()
{
if (tab_stops != NULL)
delete tab_stops;
}
void html_table::remove_cols (cols *c)
{
cols *p;
while (c != NULL) {
p = c;
c = c->next;
free(p);
}
}
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+1, linelen, 'L');
}
int html_table::get_effective_linelength (void)
{
if (columns != NULL)
return linelength - columns->left;
else
return linelength;
}
void html_table::add_indent (int indent)
{
if (columns != NULL && columns->left > indent)
add_column(0, indent, columns->left-1, 'L');
}
void html_table::emit_table_header (int space)
{
if (columns == NULL)
return;
last_col = NULL;
if (linelength > 0) {
int n = no_columns() + no_gaps();
out->nl();
out->nl();
if (space)
out->put_string("<p>");
start_space = space;
out->put_string("<table width=\"100%\" border=0 rules=\"none\" frame=\"void\"\n cols=\"").put_number(n).put_string("\" cellspacing=\"0\" cellpadding=\"0\">").nl();
out->put_string("<tr valign=\"top\" align=\"left\">").nl();
}
}
int html_table::get_right (cols *c)
{
if (c != NULL && c->right > 0)
return c->right;
if (c->next != NULL)
return c->left;
return linelength;
}
void html_table::emit_col (int n)
{
cols *c = columns;
cols *b = columns;
int width = 0;
if (last_col != NULL && n <= last_col->no)
emit_new_row();
while (c != NULL && c->no < n)
c = c->next;
if (c != NULL && c->no == n) {
if (last_col != NULL)
out->put_string("</td>").nl();
if (last_col == NULL)
b = columns;
else
b = last_col;
if (last_col != NULL) {
if (is_gap(b))
out->put_string("<td width=\"").put_number(is_gap(b)).put_string("%\"></td>").nl();
b = b->next;
}
while (b != c) {
width = ((get_right(b) - b->left) * 100)/get_effective_linelength();
out->put_string("<td width=\"").put_number(width).put_string("%\"></td>").nl();
if (is_gap(b))
out->put_string("<td width=\"").put_number(is_gap(b)).put_string("%\"></td>").nl();
b = b->next;
}
width = ((get_right(b) - b->left) * 100)/get_effective_linelength();
switch (b->alignment) {
case 'C': out->put_string("<td width=\"").put_number(width).put_string("%\" align=center>").nl();
break;
case 'R': out->put_string("<td width=\"").put_number(width).put_string("%\" align=right>").nl();
break;
default:
out->put_string("<td width=\"").put_number(width).put_string("%\">").nl();
}
last_col = b;
}
}
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("</td>").nl();
}
}
void html_table::emit_new_row (void)
{
finish_row();
out->put_string("<tr valign=\"top\" align=\"left\">").nl();
last_col = NULL;
}
void html_table::emit_finish_table (void)
{
finish_row();
out->put_string("</table>");
if (start_space)
out->put_string("</p>");
out->nl();
}
int html_table::add_column (int coln, int hstart, int hend, char align)
{
cols *c = get_column(coln);
if (c == NULL)
return insert_column(coln, hstart, hend, align);
else
return modify_column(c, hstart, hend, align);
}
cols *html_table::get_column (int coln)
{
cols *c = columns;
while (c != NULL && coln != c->no)
c = c->next;
if (c != NULL && coln == c->no)
return c;
else
return NULL;
}
int html_table::insert_column (int coln, int hstart, int hend, char align)
{
cols *c = columns;
cols *l = NULL;
cols *n = NULL;
while (c != NULL && c->no < coln) {
l = c;
c = c->next;
}
if ((l != NULL) && (hstart < l->right))
return FALSE;
if ((l != NULL) && (l->next != NULL) &&
(l->next->left < hend))
return FALSE;
n = (cols *)malloc(sizeof(cols));
if (l == NULL) {
n->next = columns;
columns = n;
} else {
n->next = l->next;
l->next = n;
}
n->left = hstart;
n->right = hend;
n->no = coln;
n->alignment = align;
return TRUE;
}
int html_table::modify_column (cols *c, int hstart, int hend, char align)
{
cols *l = columns;
while (l != NULL && l->next != c)
l = l->next;
if ((l != NULL) && (hstart < l->right))
return FALSE;
if ((c->next != NULL) && (c->next->left < hend))
return FALSE;
if (c->left > hstart)
c->left = hstart;
if (c->right < hend)
c->right = hend;
c->alignment = align;
return TRUE;
}
int html_table::find_tab_column (int pos)
{
return tab_stops->find_tab(pos)+1;
}
int html_table::find_column (int pos)
{
int p=0;
cols *c;
for (c = columns; c != NULL; c = c->next) {
if (c->left > pos)
return p;
p = c->no;
}
return p;
}
int html_table::no_columns (void)
{
int n=0;
cols *c;
for (c = columns; c != NULL; c = c->next)
n++;
return n;
}
int html_table::is_gap (cols *c)
{
if (c == NULL || c->right == 0 || c->next == NULL)
return 0;
else
return (c->next->left - c->right)*100/get_effective_linelength();
}
int html_table::no_gaps (void)
{
int n=0;
cols *c;
for (c = columns; c != NULL; c = c->next)
if (is_gap(c))
n++;
return n;
}
int html_table::get_tab_pos (int n)
{
return tab_stops->get_tab_pos(n);
}
char html_table::get_tab_align (int n)
{
return tab_stops->get_tab_align(n);
}
void html_table::dump_table (void)
{
if (columns != NULL) {
cols *c;
for (c = columns; c != NULL; c = c->next) {
printf("column %d %d..%d %c\n", c->no, c->left, c->right, c->alignment);
}
} else
tab_stops->dump_tabs();
}
html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linelength)
{
table = new html_table(op, linelength);
table->add_column(1, ind+pageoffset, linelength, 'L');
table->add_indent(pageoffset);
in = ind;
pg = pageoffset;
ll = linelength;
is_used = FALSE;
}
html_indent::~html_indent (void)
{
end();
delete table;
}
void html_indent::begin (int space)
{
if (! is_used) {
table->emit_table_header(space);
table->emit_col(1);
is_used = TRUE;
}
}
void html_indent::end (void)
{
if (is_used)
table->emit_finish_table();
is_used = FALSE;
}
void html_indent::get_reg (int *ind, int *pageoffset, int *linelength)
{
*ind = in;
*pageoffset = pg;
*linelength = ll;
}