Imported Upstream version 0.18.1.1
[platform/upstream/gettext.git] / gnulib-local / lib / html-styled-ostream.oo.c
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
43 struct html_styled_ostream : struct styled_ostream
44 {
45 fields:
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
54 static void
55 html_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
61 static void
62 html_styled_ostream::flush (html_styled_ostream_t stream)
63 {
64   html_ostream_flush (stream->html_destination);
65 }
66
67 static void
68 html_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
77 static void
78 html_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
84 static void
85 html_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
93 html_styled_ostream_t
94 html_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 }