]> git.lyx.org Git - features.git/blob - src/output_xhtml.h
Write magic paragraph label to main paragraph tag.
[features.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 attr,
121                std::string const & parid);
122         ///
123         ~ParTag() {}
124 };
125
126
127 ///
128 enum FontTypes {
129         // ranges
130         FT_EMPH,
131         FT_NOUN,
132         FT_UBAR,
133         FT_DBAR,
134         FT_WAVE,
135         FT_SOUT,
136         // bold
137         FT_BOLD,
138         // shapes
139         FT_UPRIGHT,
140         FT_ITALIC,
141         FT_SLANTED,
142         FT_SMALLCAPS,
143         // families
144         FT_ROMAN,
145         FT_SANS,
146         FT_TYPE,
147         // sizes
148         FT_SIZE_TINY,
149         FT_SIZE_SCRIPT,
150         FT_SIZE_FOOTNOTE,
151         FT_SIZE_SMALL,
152         FT_SIZE_NORMAL,
153         FT_SIZE_LARGE,
154         FT_SIZE_LARGER,
155         FT_SIZE_LARGEST,
156         FT_SIZE_HUGE,
157         FT_SIZE_HUGER,
158         FT_SIZE_INCREASE,
159         FT_SIZE_DECREASE
160 };
161
162
163 ///
164 struct FontTag : public StartTag
165 {
166         ///
167         explicit FontTag(FontTypes type);
168         ///
169         FontTag const * asFontTag() const { return this; }
170         ///
171         bool operator==(StartTag const &) const;
172         ///
173         FontTypes font_type_;
174 };
175
176
177 ///
178 struct EndFontTag : public EndTag
179 {
180         ///
181         explicit EndFontTag(FontTypes type);
182         ///
183         EndFontTag const * asFontTag() const { return this; }
184         ///
185         FontTypes font_type_;
186 };
187
188
189 // trivial struct for output of newlines
190 struct CR{};
191
192 } // namespace html
193
194 class XHTMLStream {
195 public:
196         ///
197         explicit XHTMLStream(odocstream & os);
198         ///
199         odocstream & os() { return os_; }
200         ///
201         // int & tab() { return tab_; }
202         /// closes any font tags that are eligible to be closed,
203         /// i.e., last on the tag_stack_.
204         /// \return false if there are open font tags we could not close.
205         /// because they are "blocked" by open non-font tags on the stack.
206         bool closeFontTags();
207         /// call at start of paragraph. sets a mark so we know what tags
208         /// to close at the end.
209         void startParagraph(bool keep_empty);
210         /// call at end of paragraph to clear that mark. note that this
211         /// will also close any tags still open.
212         void endParagraph();
213         ///
214         XHTMLStream & operator<<(docstring const &);
215         ///
216         XHTMLStream & operator<<(const char *);
217         ///
218         XHTMLStream & operator<<(char_type);
219         ///
220         XHTMLStream & operator<<(int);
221         ///
222         XHTMLStream & operator<<(char);
223         ///
224         XHTMLStream & operator<<(html::StartTag const &);
225         ///
226         XHTMLStream & operator<<(html::EndTag const &);
227         ///
228         XHTMLStream & operator<<(html::CompTag const &);
229         ///
230         XHTMLStream & operator<<(html::ParTag const &);
231         ///
232         XHTMLStream & operator<<(html::FontTag const &);
233         ///
234         XHTMLStream & operator<<(html::CR const &);
235         ///
236         enum EscapeSettings {
237                 ESCAPE_NONE,
238                 ESCAPE_AND, // meaning &
239                 ESCAPE_ALL  // meaning <, >, &, at present
240         };
241         /// Sets what we are going to escape on the NEXT write.
242         /// Everything is reset for the next time.
243         XHTMLStream & operator<<(EscapeSettings);
244 #if 0
245         /// This routine is for debugging the tag stack, etc. Code
246         /// for it is disabled by default, however, so you will need
247         /// to enable it if you want to use it.
248         void dumpTagStack(std::string const & msg) const;
249 #endif
250 private:
251         ///
252         void clearTagDeque();
253         ///
254         bool isTagOpen(html::StartTag const &) const;
255         ///
256         bool isTagOpen(html::EndTag const &) const;
257         ///
258         bool isTagPending(html::StartTag const &) const;
259         ///
260         void writeError(std::string const &) const;
261         ///
262         odocstream & os_;
263         ///
264         EscapeSettings escape_;
265         // What we would really like to do here is simply use a
266         // deque<StartTag>. But we want to store both StartTags and
267         // sub-classes thereof on this stack, which means we run into the
268         // so-called polymorphic class problem with the STL. We therefore have
269         // to use a deque<StartTag *>, which leads to the question who will
270         // own these pointers and how they will be deleted, so we use shared
271         // pointers.
272         ///
273         typedef std::shared_ptr<html::StartTag> TagPtr;
274         typedef std::deque<TagPtr> TagDeque;
275         ///
276         template <typename T>
277         TagPtr makeTagPtr(T const & tag) { return std::make_shared<T>(tag); }
278         ///
279         TagDeque pending_tags_;
280         ///
281         TagDeque tag_stack_;
282 };
283
284 ///
285 void xhtmlParagraphs(Text const & text,
286                        Buffer const & buf,
287                        XHTMLStream & xs,
288                        OutputParams const & runparams);
289
290 /// \return a string appropriate for setting alignment in CSS
291 /// Does NOT return "justify" for "block"
292 std::string alignmentToCSS(LyXAlignment align);
293
294 namespace html {
295 ///
296 docstring escapeChar(char_type c, XHTMLStream::EscapeSettings e);
297 /// converts a string to a form safe for links, etc
298 docstring htmlize(docstring const & str, XHTMLStream::EscapeSettings e);
299 /// cleans \param str for use as an atttribute by replacing
300 /// all non-alnum by "_"
301 docstring cleanAttr(docstring const & str);
302 /// \p c must be ASCII
303 docstring escapeChar(char c, XHTMLStream::EscapeSettings e);
304
305 } // namespace html
306 } // namespace lyx
307
308 #endif