1/* Output stream for CSS styled text, producing HTML output. 2 Copyright (C) 2006-2007 Free Software Foundation, Inc. 3 Written by Bruno Haible <bruno@clisp.org>, 2006. 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19 20/* Specification. */ 21#include "html-styled-ostream.h" 22 23#include <errno.h> 24#include <fcntl.h> 25#include <stdlib.h> 26#include <unistd.h> 27 28#include "html-ostream.h" 29 30#include "binary-io.h" 31#ifndef O_TEXT 32# define O_TEXT 0 33#endif 34 35#include "error.h" 36#include "safe-read.h" 37#include "xalloc.h" 38#include "gettext.h" 39 40#define _(str) gettext (str) 41 42 43struct html_styled_ostream : struct styled_ostream 44{ 45fields: 46 /* The destination stream. */ 47 ostream_t destination; 48 /* A HTML aware wrapper around the destination stream. */ 49 html_ostream_t html_destination; 50}; 51 52/* Implementation of ostream_t methods. */ 53 54static void 55html_styled_ostream::write_mem (html_styled_ostream_t stream, 56 const void *data, size_t len) 57{ 58 html_ostream_write_mem (stream->html_destination, data, len); 59} 60 61static void 62html_styled_ostream::flush (html_styled_ostream_t stream) 63{ 64 html_ostream_flush (stream->html_destination); 65} 66 67static void 68html_styled_ostream::free (html_styled_ostream_t stream) 69{ 70 html_ostream_free (stream->html_destination); 71 ostream_write_str (stream->destination, "</body>\n"); 72 ostream_write_str (stream->destination, "</html>\n"); 73} 74 75/* Implementation of styled_ostream_t methods. */ 76 77static void 78html_styled_ostream::begin_use_class (html_styled_ostream_t stream, 79 const char *classname) 80{ 81 html_ostream_begin_span (stream->html_destination, classname); 82} 83 84static void 85html_styled_ostream::end_use_class (html_styled_ostream_t stream, 86 const char *classname) 87{ 88 html_ostream_end_span (stream->html_destination, classname); 89} 90 91/* Constructor. */ 92 93html_styled_ostream_t 94html_styled_ostream_create (ostream_t destination, const char *css_filename) 95{ 96 html_styled_ostream_t stream = 97 XMALLOC (struct html_styled_ostream_representation); 98 99 stream->base.base.vtable = &html_styled_ostream_vtable; 100 stream->destination = destination; 101 stream->html_destination = html_ostream_create (destination); 102 103 ostream_write_str (stream->destination, "<?xml version=\"1.0\"?>\n"); 104 /* HTML 4.01 or XHTML 1.0? 105 Use HTML 4.01. This is conservative. Before switching to XHTML 1.0, 106 verify that in the output 107 - all HTML element names are in lowercase, 108 - all empty elements are denoted like <br/> or <p></p>, 109 - every attribute specification is in assignment form, like 110 <table border="1">, 111 - every <a name="..."> element also has an 'id' attribute, 112 - special characters like < > & " are escaped in the <style> and 113 <script> elements. */ 114 ostream_write_str (stream->destination, 115 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"); 116 ostream_write_str (stream->destination, "<html>\n"); 117 ostream_write_str (stream->destination, "<head>\n"); 118 if (css_filename != NULL) 119 { 120 ostream_write_str (stream->destination, "<style type=\"text/css\">\n" 121 "<!--\n"); 122 123 /* Include the contents of CSS_FILENAME literally. */ 124 { 125 int fd; 126 char buf[4096]; 127 128 fd = open (css_filename, O_RDONLY | O_TEXT); 129 if (fd < 0) 130 error (EXIT_FAILURE, errno, 131 _("error while opening \"%s\" for reading"), 132 css_filename); 133 134 for (;;) 135 { 136 size_t n_read = safe_read (fd, buf, sizeof (buf)); 137 if (n_read == SAFE_READ_ERROR) 138 error (EXIT_FAILURE, errno, _("error reading \"%s\""), 139 css_filename); 140 if (n_read == 0) 141 break; 142 143 ostream_write_mem (stream->destination, buf, n_read); 144 } 145 146 if (close (fd) < 0) 147 error (EXIT_FAILURE, errno, _("error after reading \"%s\""), 148 css_filename); 149 } 150 151 ostream_write_str (stream->destination, "-->\n" 152 "</style>\n"); 153 } 154 ostream_write_str (stream->destination, "</head>\n"); 155 ostream_write_str (stream->destination, "<body>\n"); 156 157 return stream; 158} 159