]> git.lyx.org Git - lyx.git/blob - src/output_xhtml.h
Merge branch 'master' of git.lyx.org:lyx
[lyx.git] / src / output_xhtml.h
1 // -*- C++ -*-
2 /**
3  * \file output_xhtml.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Richard Heck
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #ifndef OUTPUT_XHTML_H
13 #define OUTPUT_XHTML_H
14
15 #include "LayoutEnums.h"
16
17 #include "support/docstream.h"
18 #include "support/strfwd.h"
19
20 #include <deque>
21 #include <memory>
22
23
24 namespace lyx {
25
26 class Buffer;
27 class OutputParams;
28 class Text;
29
30 // Inspiration for the *Tag structs and for XHTMLStream
31 // came from MathStream and its cousins.
32
33 namespace html {
34
35 struct FontTag;
36 struct EndFontTag;
37
38 /// Attributes will be escaped automatically and so should NOT
39 /// be escaped before being passed to the constructor.
40 struct StartTag
41 {
42         ///
43         explicit StartTag(std::string const & tag) : tag_(tag), keepempty_(false) {}
44         ///
45         explicit StartTag(std::string const & tag, std::string const & attr,
46                 bool keepempty = false)
47                 : tag_(tag), attr_(attr), keepempty_(keepempty) {}
48         ///
49         virtual ~StartTag() {}
50         /// <tag_ attr_>
51         virtual docstring writeTag() const;
52         /// </tag_>
53         virtual docstring writeEndTag() const;
54         ///
55         virtual FontTag const * asFontTag() const { return 0; }
56         ///
57         virtual bool operator==(StartTag const & rhs) const
58                 { return tag_ == rhs.tag_; }
59         ///
60         virtual bool operator!=(StartTag const & rhs) const
61                 { return !(*this == rhs); }
62         ///
63         virtual bool operator==(FontTag const & rhs) const;
64         ///
65         std::string tag_;
66         ///
67         std::string attr_;
68         /// whether to keep things like "<tag></tag>" or discard them
69         /// you would want this for td, e.g, but maybe not for a div
70         bool keepempty_;
71 };
72
73
74 ///
75 struct EndTag
76 {
77         ///
78         explicit EndTag(std::string tag) : tag_(tag) {}
79         ///
80         virtual ~EndTag() {}
81         /// </tag_>
82         virtual docstring writeEndTag() const;
83         ///
84         bool operator==(StartTag const & rhs) const
85                 { return tag_ == rhs.tag_; }
86         ///
87         bool operator!=(StartTag const & rhs) const
88                 { return !(*this == rhs); }
89         ///
90         virtual EndFontTag const * asFontTag() const { return 0; }
91         ///
92         std::string tag_;
93 };
94
95
96 /// Tags like <img />
97 /// Attributes will be escaped automatically and so should NOT
98 /// be escaped before being passed to the constructor.
99 struct CompTag
100 {
101         ///
102         explicit CompTag(std::string const & tag)
103                 : tag_(tag) {}
104         ///
105         explicit CompTag(std::string const & tag, std::string const & attr)
106                 : tag_(tag), attr_(attr) {}
107         /// <tag_ attr_ />
108         docstring writeTag() const;
109         ///
110         std::string tag_;
111         ///
112         std::string attr_;
113 };
114
115
116 /// A special case of StartTag, used exclusively for tags that wrap paragraphs.
117 struct ParTag : public StartTag
118 {
119         ///
120         explicit ParTag(std::string const & tag, std::string const & attr,
121                std::string const & parid)
122           : StartTag(tag, attr), parid_(parid)
123         {}
124         ///
125         ~ParTag() {}
126         ///
127         docstring writeTag() const;
128         /// the "magic par label" for this paragraph
129         std::string parid_;
130 };
131
132
133 ///
134 enum FontTypes {
135         // ranges
136         FT_EMPH,
137         FT_NOUN,
138         FT_UBAR,
139         FT_DBAR,
140         FT_WAVE,
141         FT_SOUT,
142         // bold
143         FT_BOLD,
144         // shapes
145         FT_UPRIGHT,
146         FT_ITALIC,
147         FT_SLANTED,
148         FT_SMALLCAPS,
149         // families
150         FT_ROMAN,
151         FT_SANS,
152         FT_TYPE,
153         // sizes
154         FT_SIZE_TINY,
155         FT_SIZE_SCRIPT,
156         FT_SIZE_FOOTNOTE,
157         FT_SIZE_SMALL,
158         FT_SIZE_NORMAL,
159         FT_SIZE_LARGE,
160         FT_SIZE_LARGER,
161         FT_SIZE_LARGEST,
162         FT_SIZE_HUGE,
163         FT_SIZE_HUGER,
164         FT_SIZE_INCREASE,
165         FT_SIZE_DECREASE
166 };
167
168
169 ///
170 struct FontTag : public StartTag
171 {
172         ///
173         explicit FontTag(FontTypes type);
174         ///
175         FontTag const * asFontTag() const { return this; }
176         ///
177         bool operator==(StartTag const &) const;
178         ///
179         FontTypes font_type_;
180 };
181
182
183 ///
184 struct EndFontTag : public EndTag
185 {
186         ///
187         explicit EndFontTag(FontTypes type);
188         ///
189         EndFontTag const * asFontTag() const { return this; }
190         ///
191         FontTypes font_type_;
192 };
193
194
195 // trivial struct for output of newlines
196 struct CR{};
197
198 } // namespace html
199
200 class XHTMLStream {
201 public:
202         ///
203         explicit XHTMLStream(odocstream & os);
204         ///
205         odocstream & os() { return os_; }
206         ///
207         // int & tab() { return tab_; }
208         /// closes any font tags that are eligible to be closed,
209         /// i.e., last on the tag_stack_.
210         /// \return false if there are open font tags we could not close.
211         /// because they are "blocked" by open non-font tags on the stack.
212         bool closeFontTags();
213         /// call at start of paragraph. sets a mark so we know what tags
214         /// to close at the end.
215         void startParagraph(bool keep_empty);
216         /// call at end of paragraph to clear that mark. note that this
217         /// will also close any tags still open.
218         void endParagraph();
219         ///
220         XHTMLStream & operator<<(docstring const &);
221         ///
222         XHTMLStream & operator<<(const char *);
223         ///
224         XHTMLStream & operator<<(char_type);
225         ///
226         XHTMLStream & operator<<(int);
227         ///
228         XHTMLStream & operator<<(char);
229         ///
230         XHTMLStream & operator<<(html::StartTag const &);
231         ///
232         XHTMLStream & operator<<(html::EndTag const &);
233         ///
234         XHTMLStream & operator<<(html::CompTag const &);
235         ///
236         XHTMLStream & operator<<(html::ParTag const &);
237         ///
238         XHTMLStream & operator<<(html::FontTag const &);
239         ///
240         XHTMLStream & operator<<(html::CR const &);
241         ///
242         enum EscapeSettings {
243                 ESCAPE_NONE,
244                 ESCAPE_AND, // meaning &
245                 ESCAPE_ALL  // meaning <, >, &, at present
246         };
247         /// Sets what we are going to escape on the NEXT write.
248         /// Everything is reset for the next time.
249         XHTMLStream & operator<<(EscapeSettings);
250 #if 0
251         /// This routine is for debugging the tag stack, etc. Code
252         /// for it is disabled by default, however, so you will need
253         /// to enable it if you want to use it.
254         void dumpTagStack(std::string const & msg) const;
255 #endif
256 private:
257         ///
258         void clearTagDeque();
259         ///
260         bool isTagOpen(html::StartTag const &) const;
261         ///
262         bool isTagOpen(html::EndTag const &) const;
263         ///
264         bool isTagPending(html::StartTag const &) const;
265         ///
266         void writeError(std::string const &) const;
267         ///
268         odocstream & os_;
269         ///
270         EscapeSettings escape_;
271         // What we would really like to do here is simply use a
272         // deque<StartTag>. But we want to store both StartTags and
273         // sub-classes thereof on this stack, which means we run into the
274         // so-called polymorphic class problem with the STL. We therefore have
275         // to use a deque<StartTag *>, which leads to the question who will
276         // own these pointers and how they will be deleted, so we use shared
277         // pointers.
278         ///
279         typedef std::shared_ptr<html::StartTag> TagPtr;
280         typedef std::deque<TagPtr> TagDeque;
281         ///
282         template <typename T>
283         TagPtr makeTagPtr(T const & tag) { return std::make_shared<T>(tag); }
284         ///
285         TagDeque pending_tags_;
286         ///
287         TagDeque tag_stack_;
288 };
289
290 ///
291 void xhtmlParagraphs(Text const & text,
292                        Buffer const & buf,
293                        XHTMLStream & xs,
294                        OutputParams const & runparams);
295
296 /// \return a string appropriate for setting alignment in CSS
297 /// Does NOT return "justify" for "block"
298 std::string alignmentToCSS(LyXAlignment align);
299
300 namespace html {
301 ///
302 docstring escapeChar(char_type c, XHTMLStream::EscapeSettings e);
303 /// converts a string to a form safe for links, etc
304 docstring htmlize(docstring const & str, XHTMLStream::EscapeSettings e);
305 /// cleans \param str for use as an atttribute by replacing
306 /// all non-alnum by "_"
307 docstring cleanAttr(docstring const & str);
308 /// \p c must be ASCII
309 docstring escapeChar(char c, XHTMLStream::EscapeSettings e);
310
311 } // namespace html
312 } // namespace lyx
313
314 #endif