Update Spanish translation
[gnumeric.git] / plugins / html / html.c
blob901513ce483f6554a90528d7110d5223f5ab5f9c
1 /*
2 * html.c
4 * Copyright (C) 1999, 2000 Rasca, Berlin
5 * EMail: thron@gmx.de
6 * Copyright (c) 2001-2013 Andreas J. Guelzow
7 * EMail: aguelzow@pyrshep.ca
8 * Copyright 2013 Morten Welinder <terra@gnone.org>
10 * Contributors :
11 * Almer. S. Tigelaar <almer1@dds.nl>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses/>.
27 #include <gnumeric-config.h>
28 #include <gnumeric.h>
29 #include <goffice/goffice.h>
30 #include <workbook-view.h>
31 #include <workbook.h>
32 #include <sheet-style.h>
33 #include <style.h>
34 #include <style-color.h>
35 #include "html.h"
36 #include <cell.h>
37 #include <sheet.h>
38 #include <sheet-merge.h>
39 #include <value.h>
40 #include "font.h"
41 #include <cellspan.h>
42 #include <style-border.h>
43 #include <rendered-value.h>
44 #include <style.h>
45 #include <hlink.h>
46 #include <gutils.h>
48 #include <gsf/gsf-output.h>
49 #include <string.h>
52 * html_version_t:
54 * version selector
57 typedef enum {
58 HTML40 = 0,
59 HTML32 = 1,
60 HTML40F = 2,
61 XHTML = 3
62 } html_version_t;
65 * html_print_encoded:
67 * @output: the stream
68 * @str: the string
70 * print the string to output encoded all special chars
73 static void
74 html_print_encoded (GsfOutput *output, char const *str)
76 gunichar c;
78 if (str == NULL)
79 return;
80 for (; *str != '\0' ; str = g_utf8_next_char (str)) {
81 switch (*str) {
82 case '<':
83 gsf_output_puts (output, "&lt;");
84 break;
85 case '>':
86 gsf_output_puts (output, "&gt;");
87 break;
88 case '&':
89 gsf_output_puts (output, "&amp;");
90 break;
91 case '\"':
92 gsf_output_puts (output, "&quot;");
93 break;
94 case '\n':
95 gsf_output_puts (output, "<br>\n");
96 break;
97 case '\r':
98 gsf_output_puts (output, "<br>\r");
99 if( *(str+1) == '\n' ) {
100 gsf_output_puts (output, "\n");
101 str++;
103 break;
104 default:
105 c = g_utf8_get_char (str);
106 if (((c >= 0x20) && (c < 0x80)) ||
107 (c == '\n') || (c == '\r') || (c == '\t'))
108 gsf_output_write (output, 1, str);
109 else
110 gsf_output_printf (output, "&#%u;", c);
111 break;
116 static void
117 html_get_text_color (GnmCell *cell, GnmStyle const *style, guint *r, guint *g, guint *b)
119 GOColor fore = gnm_cell_get_render_color (cell);
121 if (fore == 0)
122 *r = *g = *b = 0;
123 else {
124 *r = GO_COLOR_UINT_R (fore);
125 *g = GO_COLOR_UINT_G (fore);
126 *b = GO_COLOR_UINT_B (fore);
129 static void
130 html_get_back_color (GnmStyle const *style, guint *r, guint *g, guint *b)
132 GnmColor const *color = gnm_style_get_back_color (style);
133 *r = GO_COLOR_UINT_R (color->go_color);
134 *g = GO_COLOR_UINT_G (color->go_color);
135 *b = GO_COLOR_UINT_B (color->go_color);
138 /*****************************************************************************/
141 static void
142 cb_html_add_chars (GsfOutput *output, char const *text, int len)
144 char * str;
146 g_return_if_fail (len > 0);
148 str = g_strndup (text, len);
149 html_print_encoded (output, str);
150 g_free (str);
153 static char const *
154 cb_html_attrs_as_string (GsfOutput *output, PangoAttribute *a, html_version_t version)
156 /* PangoColor const *c; */
157 char const *closure = NULL;
159 switch (a->klass->type) {
160 case PANGO_ATTR_FAMILY :
161 break; /* ignored */
162 case PANGO_ATTR_SIZE :
163 break; /* ignored */
164 case PANGO_ATTR_RISE:
165 if (((PangoAttrInt *)a)->value > 5) {
166 gsf_output_puts (output, "<sup>");
167 closure = "</sup>";
168 } else if (((PangoAttrInt *)a)->value < -5) {
169 gsf_output_puts (output, "<sub>");
170 closure = "</sub>";
172 break;
173 case PANGO_ATTR_STYLE :
174 if (((PangoAttrInt *)a)->value == PANGO_STYLE_ITALIC) {
175 gsf_output_puts (output, "<i>");
176 closure = "</i>";
178 break;
179 case PANGO_ATTR_WEIGHT :
180 if (((PangoAttrInt *)a)->value > 600){
181 gsf_output_puts (output, "<b>");
182 closure = "</b>";
184 break;
185 case PANGO_ATTR_STRIKETHROUGH :
186 if (((PangoAttrInt *)a)->value == 1) {
187 if (version == HTML32) {
188 gsf_output_puts (output, "<strike>");
189 closure = "</strike>";
190 } else {
191 gsf_output_puts
192 (output,
193 "<span style=\"text-decoration: "
194 "line-through;\">");
195 closure = "</span>";
198 break;
199 case PANGO_ATTR_UNDERLINE :
200 if ((version != HTML40) &&
201 (((PangoAttrInt *)a)->value != PANGO_UNDERLINE_NONE)) {
202 gsf_output_puts (output, "<u>");
203 closure = "</u>";
205 break;
206 case PANGO_ATTR_FOREGROUND :
207 /* c = &((PangoAttrColor *)a)->color; */
208 /* g_string_append_printf (accum, "[color=%02xx%02xx%02x", */
209 /* ((c->red & 0xff00) >> 8), */
210 /* ((c->green & 0xff00) >> 8), */
211 /* ((c->blue & 0xff00) >> 8)); */
212 break;/* ignored */
213 default :
214 if (a->klass->type ==
215 go_pango_attr_subscript_get_attr_type ()) {
216 if (((GOPangoAttrSubscript *)a)->val) {
217 gsf_output_puts (output, "<sub>");
218 closure = "</sub>";
220 } else if (a->klass->type ==
221 go_pango_attr_superscript_get_attr_type ()) {
222 if (((GOPangoAttrSuperscript *)a)->val) {
223 gsf_output_puts (output, "<sup>");
224 closure = "</sup>";
227 break; /* ignored */
230 return closure;
233 static void
234 html_new_markup (GsfOutput *output, const PangoAttrList *markup, char const *text,
235 html_version_t version)
237 int handled = 0;
238 PangoAttrIterator * iter;
239 int from, to;
240 int len = strlen (text);
241 GString *closure = g_string_new ("");
243 iter = pango_attr_list_get_iterator ((PangoAttrList *) markup);
245 do {
246 GSList *list, *l;
248 g_string_erase (closure, 0, -1);
249 pango_attr_iterator_range (iter, &from, &to);
250 from = (from > len) ? len : from; /* Since "from" can be really big! */
251 to = (to > len) ? len : to; /* Since "to" can be really big! */
252 if (from > handled)
253 cb_html_add_chars (output, text + handled, from - handled);
254 list = pango_attr_iterator_get_attrs (iter);
255 for (l = list; l != NULL; l = l->next) {
256 char const *result = cb_html_attrs_as_string (output, l->data, version);
257 if (result != NULL)
258 g_string_prepend (closure, result);
260 g_slist_free (list);
261 if (to > from)
262 cb_html_add_chars (output, text + from, to - from);
263 gsf_output_puts (output, closure->str);
264 handled = to;
265 } while (pango_attr_iterator_next (iter));
267 g_string_free (closure, TRUE);
268 pango_attr_iterator_destroy (iter);
270 return;
274 /*****************************************************************************/
276 static void
277 html_write_cell_content (GsfOutput *output, GnmCell *cell, GnmStyle const *style, html_version_t version)
279 guint r = 0;
280 guint g = 0;
281 guint b = 0;
282 char *rendered_string;
283 gboolean hidden = gnm_style_get_contents_hidden (style);
284 GnmHLink* hlink = gnm_style_get_hlink (style);
285 const guchar* hlink_target = NULL;
287 if (hlink && GNM_IS_HLINK_URL (hlink)) {
288 hlink_target = gnm_hlink_get_target (hlink);
291 if (version == HTML32 && hidden)
292 gsf_output_puts (output, "<!-- 'HIDDEN DATA' -->");
293 else {
294 if (style != NULL) {
295 if (gnm_style_get_font_italic (style))
296 gsf_output_puts (output, "<i>");
297 if (gnm_style_get_font_bold (style))
298 gsf_output_puts (output, "<b>");
299 if (gnm_style_get_font_uline (style) != UNDERLINE_NONE)
300 gsf_output_puts (output, "<u>");
301 if (font_is_monospaced (style))
302 gsf_output_puts (output, "<tt>");
303 if (gnm_style_get_font_strike (style)) {
304 if (version == HTML32)
305 gsf_output_puts (output, "<strike>");
306 else
307 gsf_output_puts (output,
308 "<span style=\"text-decoration: line-through;\">");
310 switch (gnm_style_get_font_script (style)) {
311 case GO_FONT_SCRIPT_SUB:
312 gsf_output_puts (output, "<sub>");
313 break;
314 case GO_FONT_SCRIPT_SUPER:
315 gsf_output_puts (output, "<sup>");
316 break;
317 default:
318 break;
322 if (hlink_target)
323 gsf_output_printf (output, "<a href=\"%s\">", hlink_target);
325 if (cell != NULL) {
326 const PangoAttrList * markup = NULL;
328 if (style != NULL && version != HTML40) {
329 html_get_text_color (cell, style, &r, &g, &b);
330 if (r > 0 || g > 0 || b > 0)
331 gsf_output_printf (output, "<font color=\"#%02X%02X%02X\">", r, g, b);
334 if (VALUE_IS_STRING (cell->value)
335 && (VALUE_FMT (cell->value) != NULL)
336 && go_format_is_markup (VALUE_FMT (cell->value)))
337 markup = go_format_get_markup (VALUE_FMT (cell->value));
339 if (markup != NULL) {
340 GString *str = g_string_new ("");
341 value_get_as_gstring (cell->value, str, NULL);
342 html_new_markup (output, markup, str->str, version);
343 g_string_free (str, TRUE);
344 } else {
345 rendered_string = gnm_cell_get_rendered_text (cell);
346 html_print_encoded (output, rendered_string);
347 g_free (rendered_string);
351 if (r > 0 || g > 0 || b > 0)
352 gsf_output_puts (output, "</font>");
353 if (hlink_target)
354 gsf_output_puts (output, "</a>");
355 if (style != NULL) {
356 if (gnm_style_get_font_strike (style)) {
357 if (version == HTML32)
358 gsf_output_puts (output, "</strike>");
359 else
360 gsf_output_puts (output, "</span>");
362 switch (gnm_style_get_font_script (style)) {
363 case GO_FONT_SCRIPT_SUB:
364 gsf_output_puts (output, "</sub>");
365 break;
366 case GO_FONT_SCRIPT_SUPER:
367 gsf_output_puts (output, "</sup>");
368 break;
369 default:
370 break;
372 if (font_is_monospaced (style))
373 gsf_output_puts (output, "</tt>");
374 if (gnm_style_get_font_uline (style) != UNDERLINE_NONE)
375 gsf_output_puts (output, "</u>");
376 if (gnm_style_get_font_bold (style))
377 gsf_output_puts (output, "</b>");
378 if (gnm_style_get_font_italic (style))
379 gsf_output_puts (output, "</i>");
384 static char *
385 html_get_border_style (GnmBorder *border)
387 GString *text = g_string_new (NULL);
388 char *result;
390 switch (border->line_type) {
391 case GNM_STYLE_BORDER_THIN:
392 g_string_append (text, "thin solid");
393 break;
394 case GNM_STYLE_BORDER_MEDIUM:
395 g_string_append (text, "medium solid");
396 break;
397 case GNM_STYLE_BORDER_DASHED:
398 g_string_append (text, "thin dashed");
399 break;
400 case GNM_STYLE_BORDER_DOTTED:
401 g_string_append (text, "thin dotted");
402 break;
403 case GNM_STYLE_BORDER_THICK:
404 g_string_append (text, "thick solid");
405 break;
406 case GNM_STYLE_BORDER_DOUBLE:
407 g_string_append (text, "thick double");
408 break;
409 case GNM_STYLE_BORDER_HAIR:
410 g_string_append (text, "0.5pt solid");
411 break;
412 case GNM_STYLE_BORDER_MEDIUM_DASH:
413 g_string_append (text, "medium dashed");
414 break;
415 case GNM_STYLE_BORDER_DASH_DOT:
416 g_string_append (text, "thin dashed");
417 break;
418 case GNM_STYLE_BORDER_MEDIUM_DASH_DOT:
419 g_string_append (text, "medium dashed");
420 break;
421 case GNM_STYLE_BORDER_DASH_DOT_DOT:
422 g_string_append (text, "thin dotted");
423 break;
424 case GNM_STYLE_BORDER_MEDIUM_DASH_DOT_DOT:
425 g_string_append (text, "medium dotted");
426 break;
427 case GNM_STYLE_BORDER_SLANTED_DASH_DOT:
428 g_string_append (text, "thin dashed");
429 break;
430 default:
431 break;
434 if (border->color) {
435 guint r, g, b;
436 r = GO_COLOR_UINT_R (border->color->go_color);
437 g = GO_COLOR_UINT_G (border->color->go_color);
438 b = GO_COLOR_UINT_B (border->color->go_color);
439 g_string_append_printf (text, " #%02X%02X%02X", r, g, b);
442 result = text->str;
443 g_string_free (text, FALSE);
444 return result;
447 static void
448 html_write_one_border_style_40 (GsfOutput *output, GnmBorder *border, char const *border_name)
450 char *text;
451 text = html_get_border_style (border);
452 if (text == NULL || strlen (text) == 0)
453 return;
454 gsf_output_printf (output, " %s:%s;", border_name, text);
455 g_free (text);
458 static void
459 html_write_border_style_40 (GsfOutput *output, GnmStyle const *style)
461 GnmBorder *border;
463 border = gnm_style_get_border (style, MSTYLE_BORDER_TOP);
464 if (!gnm_style_border_is_blank (border))
465 html_write_one_border_style_40 (output, border, "border-top");
466 border = gnm_style_get_border (style, MSTYLE_BORDER_BOTTOM);
467 if (!gnm_style_border_is_blank (border))
468 html_write_one_border_style_40 (output, border, "border-bottom");
469 border = gnm_style_get_border (style, MSTYLE_BORDER_LEFT);
470 if (!gnm_style_border_is_blank (border))
471 html_write_one_border_style_40 (output, border, "border-left");
472 border = gnm_style_get_border (style, MSTYLE_BORDER_RIGHT);
473 if (!gnm_style_border_is_blank (border))
474 html_write_one_border_style_40 (output, border, "border-right");
477 static void
478 html_write_border_style_40_for_merged_cell (GsfOutput *output, GnmStyle const *style,
479 Sheet *sheet, gint row, gint col)
481 GnmBorder *border;
482 GnmRange const *merge_range;
483 GnmCellPos pos;
484 pos.col = col;
485 pos.row = row;
488 border = gnm_style_get_border (style, MSTYLE_BORDER_TOP);
489 if (!gnm_style_border_is_blank (border))
490 html_write_one_border_style_40 (output, border, "border-top");
491 border = gnm_style_get_border (style, MSTYLE_BORDER_LEFT);
492 if (!gnm_style_border_is_blank (border))
493 html_write_one_border_style_40 (output, border, "border-left");
495 merge_range = gnm_sheet_merge_contains_pos (sheet, &pos);
496 if (merge_range != NULL) {
497 style = sheet_style_get (sheet, merge_range->end.col, merge_range->end.row);
498 if (style == NULL)
499 return;
502 border = gnm_style_get_border (style, MSTYLE_BORDER_BOTTOM);
503 if (!gnm_style_border_is_blank (border))
504 html_write_one_border_style_40 (output, border, "border-bottom");
505 border = gnm_style_get_border (style, MSTYLE_BORDER_RIGHT);
506 if (!gnm_style_border_is_blank (border))
507 html_write_one_border_style_40 (output, border, "border-right");
510 static void
511 write_cell (GsfOutput *output, Sheet *sheet, gint row, gint col, html_version_t version, gboolean is_merge)
513 GnmCell *cell;
514 GnmStyle const *style;
515 guint r, g, b;
517 style = sheet_style_get (sheet, col, row);
518 if (style != NULL && version != HTML32 && version != HTML40 &&
519 gnm_style_get_pattern (style) != 0 &&
520 gnm_style_is_element_set (style, MSTYLE_COLOR_BACK)) {
521 html_get_back_color (style, &r, &g, &b);
522 gsf_output_printf (output, " bgcolor=\"#%02X%02X%02X\"", r, g, b);
525 cell = sheet_cell_get (sheet, col, row);
526 if (cell != NULL) {
528 switch (gnm_style_get_align_v (style)) {
529 case GNM_VALIGN_TOP:
530 gsf_output_puts (output, " valign=\"top\" ");
531 break;
532 case GNM_VALIGN_BOTTOM:
533 gsf_output_puts (output, " valign=\"bottom\" ");
534 break;
535 case GNM_VALIGN_DISTRIBUTED:
536 case GNM_VALIGN_CENTER:
537 gsf_output_puts (output, " valign=\"center\" ");
538 break;
539 case GNM_VALIGN_JUSTIFY:
540 gsf_output_puts (output, " valign=\"baseline\" ");
541 break;
542 default:
543 break;
545 switch (gnm_style_default_halign (style, cell)) {
546 case GNM_HALIGN_RIGHT:
547 gsf_output_puts (output, " align=\"right\" ");
548 break;
549 case GNM_HALIGN_DISTRIBUTED:
550 case GNM_HALIGN_CENTER:
551 case GNM_HALIGN_CENTER_ACROSS_SELECTION:
552 gsf_output_puts (output, " align=\"center\" ");
553 break;
554 case GNM_HALIGN_LEFT:
555 gsf_output_puts (output, " align=\"left\" ");
556 break;
557 case GNM_HALIGN_JUSTIFY:
558 gsf_output_puts (output, " align=\"justify\" ");
559 break;
560 default:
561 break;
565 if (version == HTML40 || version == HTML40F || version ==XHTML) {
566 if (style != NULL) {
567 gsf_output_printf (output, " style=\"");
568 if (gnm_style_get_pattern (style) != 0 &&
569 gnm_style_is_element_set (style, MSTYLE_COLOR_BACK)) {
570 html_get_back_color (style, &r, &g, &b);
571 gsf_output_printf (output, "background:#%02X%02X%02X;", r, g, b);
573 if (cell != NULL) {
574 gint size = (int) (gnm_style_get_font_size (style) + 0.5);
575 gsf_output_printf (output, " font-size:%ipt;", size);
576 html_get_text_color (cell, style, &r, &g, &b);
577 if (r > 0 || g > 0 || b > 0)
578 gsf_output_printf (output, " color:#%02X%02X%02X;", r, g, b);
579 if (gnm_style_get_contents_hidden (style))
580 gsf_output_puts (output, " visibility:hidden;");
582 if (is_merge)
583 html_write_border_style_40_for_merged_cell (output, style, sheet, row, col);
584 else
585 html_write_border_style_40 (output, style);
586 gsf_output_printf (output, "\"");
589 gsf_output_printf (output, ">");
590 html_write_cell_content (output, cell, style, version);
591 gsf_output_puts (output, "</td>\n");
596 * write_row:
598 * @output: the stream
599 * @sheet: the gnumeric sheet
600 * @row: the row number
602 * Set up a TD node for each cell in the given row, witht eh appropriate
603 * colspan and rowspan.
604 * Call write_cell for each cell.
606 static void
607 write_row (GsfOutput *output, Sheet *sheet, gint row, GnmRange *range, html_version_t version)
609 gint col;
610 ColRowInfo const *ri = sheet_row_get_info (sheet, row);
611 if (ri->needs_respan)
612 row_calc_spans ((ColRowInfo *) ri, row, sheet);
614 for (col = range->start.col; col <= range->end.col; col++) {
615 CellSpanInfo const *the_span;
616 GnmRange const *merge_range;
617 GnmCellPos pos;
618 pos.col = col;
619 pos.row = row;
621 /* Is this a span */
622 the_span = row_span_get (ri, col);
623 if (the_span != NULL) {
624 gsf_output_printf (output, "<td colspan=\"%i\" ", the_span->right - col + 1);
625 write_cell (output, sheet, row, the_span->cell->pos.col, version, FALSE);
626 col = the_span->right;
627 continue;
630 /* is this covered by a merge */
631 merge_range = gnm_sheet_merge_contains_pos (sheet, &pos);
632 if (merge_range != NULL) {
633 if (merge_range->start.col != col ||
634 merge_range->start.row != row)
635 continue;
636 gsf_output_printf (output, "<td colspan=\"%i\" rowspan=\"%i\" ",
637 merge_range->end.col - merge_range->start.col + 1,
638 merge_range->end.row - merge_range->start.row + 1);
639 write_cell (output, sheet, row, col, version, TRUE);
640 col = merge_range->end.col;
641 continue;
643 gsf_output_puts (output, "<td ");
644 write_cell (output, sheet, row, col, version, FALSE);
649 * write_sheet:
651 * @output: the stream
652 * @sheet: the gnumeric sheet
654 * set up a table and call write_row for each row
656 static void
657 write_sheet (GsfOutput *output, Sheet *sheet,
658 html_version_t version, GOFileSaveScope save_scope)
660 GnmRange total_range;
661 gint row;
663 switch (version) {
664 case HTML40:
665 case HTML40F:
666 case XHTML:
667 gsf_output_puts (output, "<p></p><table cellspacing=\"0\" cellpadding=\"3\">\n");
668 break;
669 default:
670 gsf_output_puts (output, "<p><table border=\"1\">\n");
671 break;
674 if (save_scope != GO_FILE_SAVE_RANGE) {
675 gsf_output_puts (output, "<caption>");
676 html_print_encoded (output, sheet->name_unquoted);
677 gsf_output_puts (output, "</caption>\n");
679 total_range = sheet_get_extent (sheet, TRUE, TRUE);
680 for (row = total_range.start.row; row <= total_range.end.row; row++) {
681 gsf_output_puts (output, "<tr>\n");
682 write_row (output, sheet, row, &total_range, version);
683 gsf_output_puts (output, "</tr>\n");
685 gsf_output_puts (output, "</table>\n");
689 * html_file_save:
691 * write the html file (version of html according to version argument)
693 static void
694 html_file_save (GOFileSaver const *fs, GOIOContext *io_context,
695 WorkbookView const *wb_view, GsfOutput *output, html_version_t version)
697 Workbook *wb = wb_view_get_workbook (wb_view);
698 GOFileSaveScope save_scope;
699 GPtrArray *sel;
700 unsigned ui;
702 g_return_if_fail (fs != NULL);
703 g_return_if_fail (wb != NULL);
704 g_return_if_fail (output != NULL);
706 switch (version) {
707 case HTML32:
708 gsf_output_puts (output,
709 "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
710 "<html>\n"
711 "<head>\n\t<title>Tables</title>\n"
712 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
713 "<meta name=\"generator\" content=\"Gnumeric " GNM_VERSION_FULL " via " G_PLUGIN_FOR_HTML "\">\n"
714 "<style><!--\n"
715 "tt {\n"
716 "\tfont-family: courier;\n"
717 "}\n"
718 "td {\n"
719 "\tfont-family: helvetica, sans-serif;\n"
720 "}\n"
721 "caption {\n"
722 "\tfont-family: helvetica, sans-serif;\n"
723 "\tfont-size: 14pt;\n"
724 "\ttext-align: left;\n"
725 "}\n"
726 "--></style>\n"
727 "</head>\n<body>\n");
728 break;
729 case HTML40:
730 gsf_output_puts (output,
731 "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
732 "\t\t\"http://www.w3.org/TR/html4/strict.dtd\">\n"
733 "<html>\n"
734 "<head>\n\t<title>Tables</title>\n"
735 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
736 "<meta name=\"generator\" content=\"Gnumeric " GNM_VERSION_FULL " via " G_PLUGIN_FOR_HTML "\">\n"
737 "<style type=\"text/css\">\n"
738 "tt {\n"
739 "\tfont-family: courier;\n"
740 "}\n"
741 "td {\n"
742 "\tfont-family: helvetica, sans-serif;\n"
743 "}\n"
744 "caption {\n"
745 "\tfont-family: helvetica, sans-serif;\n"
746 "\tfont-size: 14pt;\n"
747 "\ttext-align: left;\n"
748 "}\n"
749 "</style>\n"
750 "</head>\n<body>\n");
751 break;
752 case XHTML :
753 gsf_output_puts (output,
754 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
755 "\t\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
756 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
757 "<head>\n\t<title>Tables</title>\n"
758 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"
759 "<meta name=\"generator\" content=\"Gnumeric " GNM_VERSION_FULL " via " G_PLUGIN_FOR_HTML "\" />\n"
760 "<style type=\"text/css\">\n"
761 "tt {\n"
762 "\tfont-family: courier;\n"
763 "}\n"
764 "td {\n"
765 "\tfont-family: helvetica, sans-serif;\n"
766 "}\n"
767 "caption {\n"
768 "\tfont-family: helvetica, sans-serif;\n"
769 "\tfont-size: 14pt;\n"
770 "\ttext-align: left;\n"
771 "}\n"
772 "</style>\n"
773 "</head>\n<body>\n");
774 break;
775 default:
776 break;
779 save_scope = go_file_saver_get_save_scope (fs);
781 sel = gnm_file_saver_get_sheets (fs, wb_view, TRUE);
782 for (ui = 0; ui < sel->len; ui++) {
783 Sheet *sheet = g_ptr_array_index (sel, ui);
784 write_sheet (output, sheet, version, save_scope);
786 g_ptr_array_unref (sel);
788 if (version == HTML32 || version == HTML40 || version == XHTML)
789 gsf_output_puts (output, "</body>\n</html>\n");
792 void
793 html40_file_save (GOFileSaver const *fs, GOIOContext *io_context,
794 WorkbookView const *wb_view, GsfOutput *output)
796 html_file_save (fs, io_context, wb_view, output, HTML40);
799 void
800 html32_file_save (GOFileSaver const *fs, GOIOContext *io_context,
801 WorkbookView const *wb_view, GsfOutput *output)
803 html_file_save (fs, io_context, wb_view, output, HTML32);
806 void
807 html40frag_file_save (GOFileSaver const *fs, GOIOContext *io_context,
808 WorkbookView const *wb_view, GsfOutput *output)
810 html_file_save (fs, io_context, wb_view, output, HTML40F);
813 void
814 xhtml_file_save (GOFileSaver const *fs, GOIOContext *io_context,
815 WorkbookView const *wb_view, GsfOutput *output)
817 html_file_save (fs, io_context, wb_view, output, XHTML);
820 void
821 xhtml_range_file_save (GOFileSaver const *fs, GOIOContext *io_context,
822 WorkbookView const *wb_view, GsfOutput *output)
824 /* Identical, but fs->save_scope is different */
825 xhtml_file_save (fs, io_context, wb_view, output);