/*
* html_version_t:
*
* version selector
*
*/
typedef enum {
HTML40 = 0,
HTML32 = 1,
HTML40F = 2,
XHTML = 3
} html_version_t;
/*
* html_print_encoded:
*
* @output: the stream
* @str: the string
*
* print the string to output encoded all special chars
*
*/
static void
html_print_encoded (GsfOutput *output, char const *str)
{
gunichar c;
if (str == NULL)
return;
for (; *str != '\0' ; str = g_utf8_next_char (str)) {
switch (*str) {
case '<':
gsf_output_puts (output, "<");
break;
case '>':
gsf_output_puts (output, ">");
break;
case '&':
gsf_output_puts (output, "&");
break;
case '\"':
gsf_output_puts (output, """);
break;
case '\n':
gsf_output_puts (output, "
\n");
break;
case '\r':
gsf_output_puts (output, "
\r");
if( *(str+1) == '\n' ) {
gsf_output_puts (output, "\n");
str++;
}
break;
default:
c = g_utf8_get_char (str);
if (((c >= 0x20) && (c < 0x80)) ||
(c == '\n') || (c == '\r') || (c == '\t'))
gsf_output_write (output, 1, str);
else
gsf_output_printf (output, "%u;", c);
break;
}
}
}
/*
* html_get_color:
*
* @mstyle: the cellstyle
* @t: which color
* @r: red component
* @g: green component
* @b: blue component
*
* Determine rgb components
*
*/
static void
html_get_text_color (GnmCell *cell, GnmStyle *mstyle, guint *r, guint *g, guint *b)
{
PangoColor const *fore = cell_get_render_color (cell);
if (fore == NULL)
*r = *g = *b = 0;
else {
*r = fore->red >> 8;
*g = fore->green >> 8;
*b = fore->blue >> 8;
}
}
static void
html_get_color (GnmStyle *mstyle, MStyleElementType t, guint *r, guint *g, guint *b)
{
GnmColor *color;
color = mstyle_get_color (mstyle, t);
*r = color->color.red >> 8;
*g = color->color.green >> 8;
*b = color->color.blue >> 8;
}
static void
html_write_cell_content (GsfOutput *output, GnmCell *cell, GnmStyle *mstyle, html_version_t version)
{
guint r = 0;
guint g = 0;
guint b = 0;
char *rendered_string;
gboolean hidden = mstyle_get_content_hidden (mstyle);
GnmHLink* hlink = mstyle_get_hlink (mstyle);
const guchar* hlink_target = NULL;
if (hlink && IS_GNM_HLINK_URL (hlink)) {
hlink_target = gnm_hlink_get_target (hlink);
}
if (version == HTML32 && hidden)
gsf_output_puts (output, "");
else {
if (mstyle != NULL) {
if (mstyle_get_font_italic (mstyle))
gsf_output_puts (output, "");
if (mstyle_get_font_bold (mstyle))
gsf_output_puts (output, "");
if (font_is_monospaced (mstyle))
gsf_output_puts (output, "");
}
if (hlink_target)
gsf_output_printf (output, "", hlink_target);
if (cell != NULL) {
if (mstyle != NULL && version != HTML40) {
html_get_text_color (cell, mstyle, &r, &g, &b);
if (r > 0 || g > 0 || b > 0)
gsf_output_printf (output, "", r, g, b);
}
rendered_string = cell_get_rendered_text (cell);
html_print_encoded (output, rendered_string);
g_free (rendered_string);
}
if (r > 0 || g > 0 || b > 0)
gsf_output_puts (output, "");
if (hlink_target)
gsf_output_puts (output, "");
if (mstyle != NULL) {
if (font_is_monospaced (mstyle))
gsf_output_puts (output, "");
if (mstyle_get_font_bold (mstyle))
gsf_output_puts (output, "");
if (mstyle_get_font_italic (mstyle))
gsf_output_puts (output, "");
}
}
}
static char *
html_get_border_style (GnmBorder *border)
{
GString *text = g_string_new (NULL);
char *result;
switch (border->line_type) {
case STYLE_BORDER_THIN:
g_string_append (text, "thin solid");
break;
case STYLE_BORDER_MEDIUM:
g_string_append (text, "medium solid");
break;
case STYLE_BORDER_DASHED:
g_string_append (text, "thin dashed");
break;
case STYLE_BORDER_DOTTED:
g_string_append (text, "thin dotted");
break;
case STYLE_BORDER_THICK:
g_string_append (text, "thick solid");
break;
case STYLE_BORDER_DOUBLE:
g_string_append (text, "thick double");
break;
case STYLE_BORDER_HAIR:
g_string_append (text, "0.5pt solid");
break;
case STYLE_BORDER_MEDIUM_DASH:
g_string_append (text, "medium dashed");
break;
case STYLE_BORDER_DASH_DOT:
g_string_append (text, "thin dashed");
break;
case STYLE_BORDER_MEDIUM_DASH_DOT:
g_string_append (text, "medium dashed");
break;
case STYLE_BORDER_DASH_DOT_DOT:
g_string_append (text, "thin dotted");
break;
case STYLE_BORDER_MEDIUM_DASH_DOT_DOT:
g_string_append (text, "medium dotted");
break;
case STYLE_BORDER_SLANTED_DASH_DOT:
g_string_append (text, "thin dashed");
break;
default:
break;
}
if (border->color) {
guint r, g, b;
r = border->color->color.red >> 8;
g = border->color->color.green >> 8;
b = border->color->color.blue >> 8;
g_string_append_printf (text, " #%02X%02X%02X", r, g, b);
}
result = text->str;
g_string_free (text, FALSE);
return result;
}
static void
html_write_one_border_style_40 (GsfOutput *output, GnmBorder *border, char const *border_name)
{
char *text;
text = html_get_border_style (border);
if (text == NULL || strlen (text) == 0)
return;
gsf_output_printf (output, " %s:%s;", border_name, text);
g_free (text);
}
static void
html_write_border_style_40 (GsfOutput *output, GnmStyle *mstyle)
{
GnmBorder *border;
border = mstyle_get_border (mstyle, MSTYLE_BORDER_TOP);
if (!style_border_is_blank (border))
html_write_one_border_style_40 (output, border, "border-top");
border = mstyle_get_border (mstyle, MSTYLE_BORDER_BOTTOM);
if (!style_border_is_blank (border))
html_write_one_border_style_40 (output, border, "border-bottom");
border = mstyle_get_border (mstyle, MSTYLE_BORDER_LEFT);
if (!style_border_is_blank (border))
html_write_one_border_style_40 (output, border, "border-left");
border = mstyle_get_border (mstyle, MSTYLE_BORDER_RIGHT);
if (!style_border_is_blank (border))
html_write_one_border_style_40 (output, border, "border-right");
}
static void
write_cell (GsfOutput *output, Sheet *sheet, gint row, gint col, html_version_t version)
{
GnmCell *cell;
GnmStyle *mstyle;
guint r, g, b;
mstyle = sheet_style_get (sheet, col, row);
if (mstyle != NULL && version != HTML32 && version != HTML40 &&
mstyle_get_pattern (mstyle) != 0 &&
mstyle_is_element_set (mstyle, MSTYLE_COLOR_BACK)) {
html_get_color (mstyle, MSTYLE_COLOR_BACK, &r, &g, &b);
gsf_output_printf (output, " bgcolor=\"#%02X%02X%02X\"", r, g, b);
}
cell = sheet_cell_get (sheet, col, row);
if (cell != NULL) {
switch (mstyle_get_align_v (mstyle)) {
case VALIGN_TOP:
gsf_output_puts (output, " valign=\"top\" ");
break;
case VALIGN_BOTTOM:
gsf_output_puts (output, " valign=\"bottom\" ");
break;
case VALIGN_CENTER:
gsf_output_puts (output, " valign=\"center\" ");
break;
case VALIGN_JUSTIFY:
gsf_output_puts (output, " valign=\"baseline\" ");
break;
default:
break;
}
switch (style_default_halign(mstyle, cell)) {
case HALIGN_RIGHT:
gsf_output_puts (output, " align=\"right\" ");
break;
case HALIGN_CENTER:
case HALIGN_CENTER_ACROSS_SELECTION:
gsf_output_puts (output, " align=\"center\" ");
break;
case HALIGN_LEFT:
gsf_output_puts (output, " align=\"left\" ");
break;
case HALIGN_JUSTIFY:
gsf_output_puts (output, " align=\"justify\" ");
break;
default:
break;
}
}
if (version == HTML40 || version == HTML40F) {
if (mstyle != NULL) {
gsf_output_printf (output, " style=\"");
if (mstyle_get_pattern (mstyle) != 0 &&
mstyle_is_element_set (mstyle, MSTYLE_COLOR_BACK)) {
html_get_color (mstyle, MSTYLE_COLOR_BACK, &r, &g, &b);
gsf_output_printf (output, "background:#%02X%02X%02X;", r, g, b);
}
if (cell != NULL) {
gint size = (int) (mstyle_get_font_size (mstyle) + 0.5);
gsf_output_printf (output, " font-size:%ipt;", size);
html_get_text_color (cell, mstyle, &r, &g, &b);
if (r > 0 || g > 0 || b > 0)
gsf_output_printf (output, " color:#%02X%02X%02X;", r, g, b);
if (mstyle_get_content_hidden (mstyle))
gsf_output_puts (output, " visibility:hidden;");
}
html_write_border_style_40 (output, mstyle);
gsf_output_printf (output, "\"");
}
}
gsf_output_printf (output, ">");
html_write_cell_content (output, cell, mstyle, version);
gsf_output_puts (output, "\n");
}
/*
* write_row:
*
* @output: the stream
* @sheet: the gnumeric sheet
* @row: the row number
*
* Set up a TD node for each cell in the given row, witht eh appropriate
* colspan and rowspan.
* Call write_cell for each cell.
*/
static void
write_row (GsfOutput *output, Sheet *sheet, gint row, GnmRange *range, html_version_t version)
{
gint col;
ColRowInfo const * ri;
ri = sheet_row_get_info (sheet, row);
if (ri->needs_respan)
row_calc_spans ((ColRowInfo *) ri, sheet);
for (col = range->start.col; col <= range->end.col; col++) {
CellSpanInfo const *the_span;
GnmRange const *merge_range;
GnmCellPos pos;
pos.col = col;
pos.row = row;
/* Is this a span */
the_span = row_span_get (ri, col);
if (the_span != NULL) {
gsf_output_printf (output, "right - col + 1);
write_cell (output, sheet, row, the_span->cell->pos.col, version);
col = the_span->right;
continue;
}
/* is this covered by a merge */
merge_range = sheet_merge_contains_pos (sheet, &pos);
if (merge_range != NULL) {
if (merge_range->start.col != col ||
merge_range->start.row != row)
continue;
gsf_output_printf (output, " | end.col - merge_range->start.col + 1,
merge_range->end.row - merge_range->start.row + 1);
write_cell (output, sheet, row, col, version);
col = merge_range->end.col;
continue;
}
gsf_output_puts (output, " | \n");
break;
case XHTML:
gsf_output_puts (output, "\n");
break;
default:
gsf_output_puts (output, "\n");
break;
}
if (save_scope != FILE_SAVE_RANGE) {
gsf_output_puts (output, "");
html_print_encoded (output, sheet->name_unquoted);
gsf_output_puts (output, "\n");
}
total_range = sheet_get_extent (sheet, TRUE);
for (row = total_range.start.row; row <= total_range.end.row; row++) {
gsf_output_puts (output, "\n");
write_row (output, sheet, row, &total_range,
(version == XHTML) ? HTML40 : version);
gsf_output_puts (output, " \n");
}
gsf_output_puts (output, " \n");
}
/*
* html_file_save:
*
* write the html file (version of html according to version argument)
*/
static void
html_file_save (GnmFileSaver const *fs, IOContext *io_context,
WorkbookView const *wb_view, GsfOutput *output, html_version_t version)
{
GList *sheets, *ptr;
Workbook *wb = wb_view_workbook (wb_view);
FileSaveScope save_scope;
g_return_if_fail (fs != NULL);
g_return_if_fail (wb != NULL);
g_return_if_fail (output != NULL);
switch (version) {
case HTML32:
gsf_output_puts (output,
"\n"
"\n"
"\n\tTables\n"
"\n"
"\t\n"
"\n"
"\n\n");
break;
case HTML40:
gsf_output_puts (output,
"\n"
"\n"
"\n\tTables\n"
"\n"
"\t\n"
"\n"
"\n\n");
break;
case XHTML :
gsf_output_puts (output,
"\n"
"\n"
"\n"
"\n\tTables\n"
"\n"
"\t\n"
"\n"
"\n\n");
break;
default:
break;
}
sheets = workbook_sheets (wb);
save_scope = gnm_file_saver_get_save_scope (fs);
for (ptr = sheets ; ptr != NULL ; ptr = ptr->next) {
write_sheet (output, (Sheet *) ptr->data, version, save_scope);
}
g_list_free (sheets);
if (version == HTML32 || version == HTML40 || version == XHTML)
gsf_output_puts (output, "\n\n");
}
void
html40_file_save (GnmFileSaver const *fs, IOContext *io_context,
WorkbookView const *wb_view, GsfOutput *output)
{
html_file_save (fs, io_context, wb_view, output, HTML40);
}
void
html32_file_save (GnmFileSaver const *fs, IOContext *io_context,
WorkbookView const *wb_view, GsfOutput *output)
{
html_file_save (fs, io_context, wb_view, output, HTML32);
}
void
html40frag_file_save (GnmFileSaver const *fs, IOContext *io_context,
WorkbookView const *wb_view, GsfOutput *output)
{
html_file_save (fs, io_context, wb_view, output, HTML40F);
}
void
xhtml_file_save (GnmFileSaver const *fs, IOContext *io_context,
WorkbookView const *wb_view, GsfOutput *output)
{
html_file_save (fs, io_context, wb_view, output, XHTML);
}
void
xhtml_range_file_save (GnmFileSaver const *fs, IOContext *io_context,
WorkbookView const *wb_view, GsfOutput *output)
{
/* Identical, but fs->save_scope is different */
xhtml_file_save (fs, io_context, wb_view, output);
}
|