]> git.lyx.org Git - lyx.git/blob - src/xml.h
Fixup 1d08af62: unused variable
[lyx.git] / src / xml.h
1 // -*- C++ -*-
2 /**
3  * \file xml.h
4  * This file is part of LyX, the document processor.
5  * License details can be found in the file COPYING.
6  *
7  * \author José Matos
8  * \author John Levon
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #ifndef XML_H
14 #define XML_H
15
16 #include "support/docstring.h"
17
18 #include <deque>
19 #include <memory>
20
21 namespace lyx {
22
23 class Buffer;
24 class Paragraph;
25 class OutputParams;
26
27 // Inspiration for the *Tag structs and for XMLStream
28 // came from MathMLStream and its cousins.
29
30 namespace xml {
31 struct StartTag;
32 struct EndTag;
33 struct CompTag;
34 struct ParTag;
35 struct FontTag;
36 struct CR;
37 }
38
39 class XMLStream {
40 public:
41         ///
42         explicit XMLStream(odocstream & os): os_(os), escape_(ESCAPE_ALL), is_last_tag_cr_(true) {}
43         ///
44         odocstream & os() { return os_; }
45         ///
46         // int & tab() { return tab_; }
47         /// closes any font tags that are eligible to be closed,
48         /// i.e., last on the tag_stack_.
49         /// \return false if there are open font tags we could not close.
50         /// because they are "blocked" by open non-font tags on the stack.
51         bool closeFontTags();
52         /// sets a mark so we know what tags to close at the end.
53         /// normally called at the start of a paragraph.
54         void startDivision(bool keep_empty);
55         /// clears the mark set by previous method.
56         /// there should not be any other tags open before it on the stack,
57         /// but if there are, we will close them.
58         void endDivision();
59         ///
60         XMLStream & operator<<(docstring const &);
61         ///
62         XMLStream & operator<<(const char *);
63         ///
64         XMLStream & operator<<(char_type);
65         ///
66         XMLStream & operator<<(int);
67         ///
68         XMLStream & operator<<(char);
69         ///
70         XMLStream & operator<<(xml::StartTag const &);
71         ///
72         XMLStream & operator<<(xml::EndTag const &);
73         ///
74         XMLStream & operator<<(xml::CompTag const &);
75         ///
76         XMLStream & operator<<(xml::ParTag const &);
77         ///
78         XMLStream & operator<<(xml::FontTag const &);
79         ///
80         XMLStream & operator<<(xml::CR const &);
81         ///
82         enum EscapeSettings {
83                 ESCAPE_NONE,
84                 ESCAPE_AND, // meaning &
85                 ESCAPE_ALL, // meaning <, >, &, at present, except things that are forbidden in comments
86                 ESCAPE_COMMENTS // Anything that is forbidden within comments
87         };
88         /// Sets what we are going to escape on the NEXT write.
89         /// Everything is reset for the next time.
90         XMLStream & operator<<(EscapeSettings);
91         /// This routine is for debugging the tag stack, etc. Code
92         /// for it is disabled by default, however, so you will need
93         /// to enable it if you want to use it.
94         void dumpTagStack(std::string const & msg);
95         ///
96         bool isTagOpen(xml::StartTag const &, int maxdepth = -1) const;
97         ///
98         bool isTagOpen(xml::EndTag const &, int maxdepth = -1) const;
99         ///
100         bool isTagPending(xml::StartTag const &, int maxdepth = -1) const;
101         /// Is the last tag that was added to the stream a new line (CR)? This is mostly to known
102         /// whether a new line must be added. Therefore, consider that an empty stream just had a CR,
103         /// that simplifies the logic using this code.
104         bool isLastTagCR() const { return is_last_tag_cr_; }
105         ///
106         void writeError(std::string const &);
107         ///
108         void writeError(docstring const &);
109         ///
110         typedef std::shared_ptr<xml::StartTag> TagPtr;
111         /// Returns the last element on the tag stack. XMLStream keeps ownership of the item.
112         TagPtr getLastStackTag();
113 private:
114         ///
115         void clearTagDeque();
116         ///
117         odocstream & os_;
118         ///
119         EscapeSettings escape_;
120         // What we would really like to do here is simply use a
121         // deque<StartTag>. But we want to store both StartTags and
122         // sub-classes thereof on this stack, which means we run into the
123         // so-called polymorphic class problem with the STL. We therefore have
124         // to use a deque<StartTag *>, which leads to the question who will
125         // own these pointers and how they will be deleted, so we use shared
126         // pointers.
127         ///
128         typedef std::deque<TagPtr> TagDeque;
129         ///
130         template <typename T>
131         TagPtr makeTagPtr(T const & tag) { return std::make_shared<T>(tag); }
132         ///
133         TagDeque pending_tags_;
134         ///
135         TagDeque tag_stack_;
136         ///
137         bool is_last_tag_cr_;
138 };
139
140 namespace xml {
141
142 /// Escape the given character, if necessary, to an entity.
143 docstring escapeChar(char_type c, XMLStream::EscapeSettings e);
144
145 /// Escape the given character, if necessary, to an entity.
146 /// \param c must be ASCII
147 docstring escapeChar(char c, XMLStream::EscapeSettings e);
148
149 /// Escape a word instead of a single character
150 docstring escapeString(docstring const & raw, XMLStream::EscapeSettings e=XMLStream::ESCAPE_ALL);
151
152 /// cleans \param str for use as an attribute by replacing all non-altnum by "_"
153 docstring cleanAttr(docstring const & str);
154
155 /// replaces illegal characters from ID attributes
156 docstring cleanID(docstring const &orig);
157
158 /// returns a unique numeric ID
159 docstring uniqueID(docstring const & label);
160
161 /// determines whether a string only contains space characters
162 bool isNotOnlySpace(docstring const & str);
163
164 /// trims the string to the left, i.e. remove any space-like character at the beginning of the string
165 docstring trimLeft(docstring const & str);
166
167 struct FontTag;
168 struct EndFontTag;
169
170 /// Attributes will be escaped automatically and so should NOT
171 /// be escaped before being passed to the constructor.
172 struct StartTag
173 {
174         ///
175         explicit StartTag(std::string const & tag) : tag_(from_ascii(tag)), keepempty_(false), tagtype_("none") {}
176         ///
177         explicit StartTag(docstring const & tag) : tag_(tag), keepempty_(false), tagtype_("none") {}
178         ///
179         explicit StartTag(docstring const & tag, docstring const & attr,
180                                           bool keepempty = false, std::string const & tagtype = "none")
181                         : tag_(tag), attr_(attr), keepempty_(keepempty), tagtype_(tagtype) {}
182         ///
183         explicit StartTag(std::string const & tag, std::string const & attr,
184                                           bool keepempty = false, std::string const & tagtype = "none")
185                         : tag_(from_ascii(tag)), attr_(from_utf8(attr)), keepempty_(keepempty), tagtype_(tagtype) {}
186         ///
187         explicit StartTag(std::string const & tag, docstring const & attr,
188                                           bool keepempty = false, std::string const & tagtype = "none")
189                         : tag_(from_ascii(tag)), attr_(attr), keepempty_(keepempty), tagtype_(tagtype) {}
190         ///
191         virtual ~StartTag() = default;
192         /// <tag_ attr_>
193         virtual docstring writeTag() const;
194         /// </tag_>
195         virtual docstring writeEndTag() const;
196         ///
197         virtual FontTag const * asFontTag() const { return nullptr; }
198         ///
199         virtual bool operator==(StartTag const & rhs) const
200         { return tag_ == rhs.tag_; }
201         ///
202         virtual bool operator!=(StartTag const & rhs) const
203         { return !(*this == rhs); }
204         ///
205         virtual bool operator==(FontTag const & rhs) const;
206         ///
207         docstring tag_;
208         ///
209         docstring attr_;
210         /// whether to keep things like "<tag></tag>" or discard them
211         /// you would want this for td, e.g, but maybe not for a div
212         bool keepempty_;
213         /// Type of tag for new-line behaviour. Either "paragraph", "inline", "block", or "none" (default).
214         std::string tagtype_;
215 };
216
217
218 ///
219 struct EndTag
220 {
221         ///
222         explicit EndTag(std::string const & tag, std::string const & tagtype = "none")
223                 : tag_(from_ascii(tag)), tagtype_(tagtype) {}
224         ///
225         explicit EndTag(docstring const & tag, std::string const & tagtype = "none")
226                 : tag_(tag), tagtype_(tagtype) {}
227         ///
228         virtual ~EndTag() = default;
229         /// </tag_>
230         virtual docstring writeEndTag() const;
231         ///
232         bool operator==(StartTag const & rhs) const
233         { return tag_ == rhs.tag_; }
234         ///
235         bool operator!=(StartTag const & rhs) const
236         { return !(*this == rhs); }
237         ///
238         virtual EndFontTag const * asFontTag() const { return nullptr; }
239         ///
240         docstring tag_;
241         /// Type of tag for new-line behaviour. Either "paragraph", "inline", "block", or "none" (default).
242         /// The value should match that of the corresponding xml::StartTag.
243         std::string tagtype_;
244 };
245
246
247 /// Tags like <img />
248 /// Attributes will be escaped automatically and so should NOT
249 /// be escaped before being passed to the constructor.
250 struct CompTag
251 {
252         ///
253         explicit CompTag(std::string const & tag)
254                         : tag_(from_utf8(tag)), tagtype_("none") {}
255         ///
256         explicit CompTag(docstring const & tag)
257                         : tag_(tag), tagtype_("none") {}
258         ///
259         explicit CompTag(std::string const & tag, std::string const & attr, std::string const & tagtype = "none")
260                         : tag_(from_utf8(tag)), attr_(from_utf8(attr)), tagtype_(tagtype) {}
261         ///
262         explicit CompTag(std::string const & tag, docstring const & attr, std::string const & tagtype = "none")
263                         : tag_(from_utf8(tag)), attr_(attr), tagtype_(tagtype) {}
264         ///
265         explicit CompTag(docstring const & tag, std::string const & attr, std::string const & tagtype = "none")
266                         : tag_(tag), attr_(from_utf8(attr)), tagtype_(tagtype) {}
267         ///
268         explicit CompTag(docstring const & tag, docstring const & attr, std::string const & tagtype = "none")
269                         : tag_(tag), attr_(attr), tagtype_(tagtype) {}
270         /// <tag_ attr_ />
271         docstring writeTag() const;
272         ///
273         docstring tag_;
274         ///
275         docstring attr_;
276         /// Type of tag for new-line behaviour. Either "paragraph", "inline", "block", or "none" (default).
277         std::string tagtype_;
278 };
279
280
281 /// A special case of StartTag, used exclusively for tags that wrap paragraphs.
282 struct ParTag : public StartTag
283 {
284         ///
285         explicit ParTag(std::string const & tag, const std::string & attr): StartTag(tag, from_utf8(attr)) {}
286         ///
287         ~ParTag() override = default;
288 };
289
290
291 ///
292 enum FontTypes {
293         // ranges
294         FT_EMPH,
295         FT_NOUN,
296         FT_UBAR,
297         FT_DBAR,
298         FT_WAVE,
299         FT_SOUT,
300         FT_XOUT,
301         // bold
302         FT_BOLD,
303         // shapes
304         FT_UPRIGHT,
305         FT_ITALIC,
306         FT_SLANTED,
307         FT_SMALLCAPS,
308         // families
309         FT_ROMAN,
310         FT_SANS,
311         FT_TYPE,
312         // sizes
313         FT_SIZE_TINY,
314         FT_SIZE_SCRIPT,
315         FT_SIZE_FOOTNOTE,
316         FT_SIZE_SMALL,
317         FT_SIZE_NORMAL,
318         FT_SIZE_LARGE,
319         FT_SIZE_LARGER,
320         FT_SIZE_LARGEST,
321         FT_SIZE_HUGE,
322         FT_SIZE_HUGER,
323         FT_SIZE_INCREASE,
324         FT_SIZE_DECREASE
325
326         // When updating this list, also update fontToTag in both output_docbook.cpp and output_xhtml.cpp,
327         // fontToRole in output_docbook.cpp, and fontToAttribute in output_xhtml.cpp.
328 };
329
330
331 ///
332 struct FontTag : public StartTag
333 {
334         ///
335         FontTag(docstring const & tag, FontTypes type): StartTag(tag), font_type_(type) {}
336         ///
337         FontTag(std::string const & tag, FontTypes type): StartTag(from_utf8(tag)), font_type_(type) {}
338         ///
339         FontTag(docstring const & tag, docstring const & attr, FontTypes type): StartTag(tag, attr), font_type_(type) {}
340         ///
341         FontTag(std::string const & tag, std::string const & attr, FontTypes type): StartTag(from_utf8(tag), from_utf8(attr)), font_type_(type) {}
342         ///
343         FontTag const * asFontTag() const override { return this; }
344         ///
345         bool operator==(StartTag const &) const override;
346         ///
347         FontTypes font_type_;
348 };
349
350
351 ///
352 struct EndFontTag : public EndTag
353 {
354         ///
355         EndFontTag(docstring const & tag, FontTypes type): EndTag(tag), font_type_(type) {}
356         ///
357         EndFontTag(std::string const & tag, FontTypes type): EndTag(from_utf8(tag)), font_type_(type) {}
358         ///
359         EndFontTag const * asFontTag() const override { return this; }
360         ///
361         FontTypes font_type_;
362 };
363
364
365 // trivial struct for output of newlines
366 struct CR{};
367
368 // an illegal tag for internal use
369 xml::StartTag const parsep_tag("&LyX_parsep_tag&");
370
371 /// Open tag
372 void openTag(odocstream & os, std::string const & name,
373              std::string const & attribute = std::string());
374
375 /// Open tag
376 void openTag(Buffer const & buf, odocstream & os,
377              OutputParams const & runparams, Paragraph const & par);
378
379 /// Close tag
380 void closeTag(odocstream & os, std::string const & name);
381
382 /// Close tag
383 void closeTag(odocstream & os, Paragraph const & par);
384
385 // Convenience functions to open and close tags. First, very low-level ones to ensure a consistent new-line behaviour.
386 // Block style:
387 //        Content before
388 //        <blocktag>
389 //          Contents of the block.
390 //        </blocktag>
391 //        Content after
392 // Paragraph style:
393 //        Content before
394 //          <paratag>Contents of the paragraph.</paratag>
395 //        Content after
396 // Inline style:
397 //    Content before<inlinetag>Contents of the paragraph.</inlinetag>Content after
398
399 ///
400 void openTag(XMLStream & xs, const docstring & tag, const docstring & attr, const std::string & tagtype);
401 ///
402 void openTag(XMLStream & xs, const std::string & tag, const std::string & attr, const std::string & tagtype);
403 ///
404 void openTag(XMLStream & xs, const docstring & tag, const std::string & attr, const std::string & tagtype);
405 ///
406 void openTag(XMLStream & xs, const std::string & tag, const docstring & attr, const std::string & tagtype);
407 ///
408 void closeTag(XMLStream & xs, const docstring & tag, const std::string & tagtype);
409 ///
410 void closeTag(XMLStream & xs, const std::string & tag, const std::string & tagtype);
411 ///
412 void compTag(XMLStream & xs, const docstring & tag, const docstring & attr, const std::string & tagtype);
413 ///
414 void compTag(XMLStream & xs, const std::string & tag, const std::string & attr, const std::string & tagtype);
415 ///
416 void compTag(XMLStream & xs, const docstring & tag, const std::string & attr, const std::string & tagtype);
417 ///
418 void compTag(XMLStream & xs, const std::string & tag, const docstring & attr, const std::string & tagtype);
419
420 } // namespace xml
421
422 } // namespace lyx
423
424 #endif // XML_H