#include "driver.h"
#include "stringclass.h"
#include "cset.h"
#include "html-table.h"
#include "ctype.h"
#include "html.h"
#include "html-text.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;
delete 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 = new tab_position;
last = tab;
} else {
last->next = new tab_position;
last = last->next;
}
last->alignment = align;
last->position = total;
last->next = NULL;
}
}
void tabs::check_init (const char *s)
{
if (tab == NULL)
init(s);
}
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)
: out(op), columns(NULL), 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;
delete c;
c = columns;
}
}
void html_table::remove_cols (cols *c)
{
cols *p;
while (c != NULL) {
p = c;
c = c->next;
delete 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, linelength, '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, 'L');
}
void html_table::emit_table_header (int space)
{
if (columns == NULL)
return;
last_col = NULL;
if (linelength > 0) {
out->nl();
out->nl();
out->put_string("<table width=\"100%\"")
.put_string(" border=0 rules=\"none\" frame=\"void\"\n")
.put_string(" cellspacing=\"0\" cellpadding=\"0\"");
out->put_string(">")
.nl();
out->put_string("<tr valign=\"top\" align=\"left\"");
if (space) {
out->put_string(" style=\"margin-top: ");
out->put_string(STYLE_VERTICAL_SPACE);
out->put_string("\"");
}
out->put_string(">").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::set_space (int space)
{
start_space = space;
}
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)*100 + get_effective_linelength()/2)
/ get_effective_linelength()
- (b->left*100 + get_effective_linelength()/2)
/get_effective_linelength();
if (width)
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)*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("<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\"");
if (start_space) {
out->put_string(" style=\"margin-top: ");
out->put_string(STYLE_VERTICAL_SPACE);
out->put_string("\"");
}
out->put_string(">").nl();
start_space = FALSE;
last_col = NULL;
}
void html_table::emit_finish_table (void)
{
finish_row();
out->put_string("</table>");
}
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 = columns;
cols *n = NULL;
while (c != NULL && c->no < coln) {
l = c;
c = c->next;
}
if (l != NULL && l->no>coln && hend > l->left)
return FALSE;
l = NULL;
c = columns;
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 = new 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*100 + get_effective_linelength()/2)
/ get_effective_linelength()
- (c->right*100 + get_effective_linelength()/2)
/ 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;
}
html_indent::~html_indent (void)
{
end();
delete table;
}
void html_indent::begin (int space)
{
if (in + pg == 0) {
if (space) {
table->out->put_string(" style=\"margin-top: ");
table->out->put_string(STYLE_VERTICAL_SPACE);
table->out->put_string("\"");
}
}
else {
table->out->put_string(" style=\"margin-left:")
.put_number(((in + pg) * 100 + ll/2) / ll -
(ll/2)/ll)
.put_string("%;");
if (space) {
table->out->put_string(" margin-top: ");
table->out->put_string(STYLE_VERTICAL_SPACE);
}
table->out->put_string("\"");
}
}
void html_indent::end (void)
{
}
void html_indent::get_reg (int *ind, int *pageoffset, int *linelength)
{
*ind = in;
*pageoffset = pg;
*linelength = ll;
}