]> git.lyx.org Git - lyx.git/blob - src/output_xhtml.h
Fix text direction issue for InsetInfo in RTL context
[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 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         FT_XOUT,
137         // bold
138         FT_BOLD,
139         // shapes
140         FT_UPRIGHT,
141         FT_ITALIC,
142         FT_SLANTED,
143         FT_SMALLCAPS,
144         // families
145         FT_ROMAN,
146         FT_SANS,
147         FT_TYPE,
148         // sizes
149         FT_SIZE_TINY,
150         FT_SIZE_SCRIPT,
151         FT_SIZE_FOOTNOTE,
152         FT_SIZE_SMALL,
153         FT_SIZE_NORMAL,
154         FT_SIZE_LARGE,
155         FT_SIZE_LARGER,
156         FT_SIZE_LARGEST,
157         FT_SIZE_HUGE,
158         FT_SIZE_HUGER,
159         FT_SIZE_INCREASE,
160         FT_SIZE_DECREASE
161 };
162
163
164 ///
165 struct FontTag : public StartTag
166 {
167         ///
168         explicit FontTag(FontTypes type);
169         ///
170         FontTag const * asFontTag() const { return this; }
171         ///
172         bool operator==(StartTag const &) const;
173         ///
174         FontTypes font_type_;
175 };
176
177
178 ///
179 struct EndFontTag : public EndTag
180 {
181         ///
182         explicit EndFontTag(FontTypes type);
183         ///
184         EndFontTag const * asFontTag() const { return this; }
185         ///
186         FontTypes font_type_;
187 };
188
189
190 // trivial struct for output of newlines
191 struct CR{};
192
193 } // namespace html
194
195 class XHTMLStream {
196 public:
197         ///
198         explicit XHTMLStream(odocstream & os);
199         ///
200         odocstream & os() { return os_; }
201         ///
202         // int & tab() { return tab_; }
203         /// closes any font tags that are eligible to be closed,
204         /// i.e., last on the tag_stack_.
205         /// \return false if there are open font tags we could not close.
206         /// because they are "blocked" by open non-font tags on the stack.
207         bool closeFontTags();
208         /// sets a mark so we know what tags to close at the end.
209         /// normally called at the start of a paragraph.
210         void startDivision(bool keep_empty);
211         /// clears the mark set by previous method.
212         /// there should not be any other tags open before it on the stack,
213         /// but if there are, we will close them.
214         void endDivision();
215         ///
216         XHTMLStream & operator<<(docstring const &);
217         ///
218         XHTMLStream & operator<<(const char *);
219         ///
220         XHTMLStream & operator<<(char_type);
221         ///
222         XHTMLStream & operator<<(int);
223         ///
224         XHTMLStream & operator<<(char);
225         ///
226         XHTMLStream & operator<<(html::StartTag const &);
227         ///
228         XHTMLStream & operator<<(html::EndTag const &);
229         ///
230         XHTMLStream & operator<<(html::CompTag const &);
231         ///
232         XHTMLStream & operator<<(html::ParTag const &);
233         ///
234         XHTMLStream & operator<<(html::FontTag const &);
235         ///
236         XHTMLStream & operator<<(html::CR const &);
237         ///
238         enum EscapeSettings {
239                 ESCAPE_NONE,
240                 ESCAPE_AND, // meaning &
241                 ESCAPE_ALL  // meaning <, >, &, at present
242         };
243         /// Sets what we are going to escape on the NEXT write.
244         /// Everything is reset for the next time.
245         XHTMLStream & operator<<(EscapeSettings);
246         /// This routine is for debugging the tag stack, etc. Code
247         /// for it is disabled by default, however, so you will need
248         /// to enable it if you want to use it.
249         void dumpTagStack(std::string const & msg);
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