]> git.lyx.org Git - lyx.git/blob - src/tex2lyx/Context.cpp
tex2lyx: support for multiple indices and subindices
[lyx.git] / src / tex2lyx / Context.cpp
1 /**
2  * \file Context.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jean-Marc Lasgouttes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "Context.h"
14 #include "Layout.h"
15
16 #include "support/lstrings.h"
17
18 #include <iostream>
19
20 using namespace std;
21 using namespace lyx::support;
22
23 namespace lyx {
24
25 namespace {
26
27 void end_layout(ostream & os)
28 {
29         os << "\n\\end_layout\n";
30 }
31
32
33 void begin_deeper(ostream & os)
34 {
35         os << "\n\\begin_deeper";
36 }
37
38
39 void end_deeper(ostream & os)
40 {
41         os << "\n\\end_deeper";
42 }
43
44 }
45
46
47 bool operator==(TeXFont const & f1, TeXFont const & f2)
48 {
49         return
50                 f1.size == f2.size &&
51                 f1.family == f2.family &&
52                 f1.series == f2.series &&
53                 f1.shape == f2.shape &&
54                 f1.language == f2.language;
55 }
56
57
58 void output_font_change(ostream & os, TeXFont const & oldfont,
59                         TeXFont const & newfont)
60 {
61         if (oldfont.family != newfont.family)
62                 os << "\n\\family " << newfont.family << '\n';
63         if (oldfont.series != newfont.series)
64                 os << "\n\\series " << newfont.series << '\n';
65         if (oldfont.shape != newfont.shape)
66                 os << "\n\\shape " << newfont.shape << '\n';
67         if (oldfont.size != newfont.size)
68                 os << "\n\\size " << newfont.size << '\n';
69         if (oldfont.language != newfont.language)
70                 os << "\n\\lang " << newfont.language << '\n';
71 }
72
73
74 TeXFont Context::normalfont;
75 bool Context::empty = true;
76
77
78 Context::Context(bool need_layout_,
79                  TeX2LyXDocClass const & textclass_,
80                  Layout const * layout_, Layout const * parent_layout_,
81                  TeXFont font_)
82         : need_layout(need_layout_),
83           need_end_layout(false), need_end_deeper(false),
84           has_item(false), deeper_paragraph(false),
85           new_layout_allowed(true), textclass(textclass_),
86           layout(layout_), parent_layout(parent_layout_),
87           font(font_)
88 {
89         if (!layout)
90                 layout = &textclass.defaultLayout();
91         if (!parent_layout)
92                 parent_layout = &textclass.defaultLayout();
93 }
94
95
96 Context::~Context()
97 {
98         if (!par_extra_stuff.empty())
99                 cerr << "Bug: Ignoring par-level extra stuff '"
100                      << par_extra_stuff << '\'' << endl;
101 }
102
103
104 void Context::begin_layout(ostream & os, Layout const * const & l)
105 {
106         os << "\n\\begin_layout " << to_utf8(l->name()) << "\n";
107         if (!extra_stuff.empty()) {
108                 os << extra_stuff;
109         }
110         if (!par_extra_stuff.empty()) {
111                 os << par_extra_stuff;
112                 par_extra_stuff.erase();
113         }
114         // FIXME: This is not enough for things like
115         // \\Huge par1 \\par par2
116         // FIXME: If the document language is not english this outputs a
117         // superflous language change. Fortunately this is only file format
118         // bloat and does not change the TeX export of LyX.
119         output_font_change(os, normalfont, font);
120 }
121
122
123 void Context::check_layout(ostream & os)
124 {
125         if (need_layout) {
126                 check_end_layout(os);
127
128                 // are we in a list-like environment?
129                 if (layout->isEnvironment()
130                     && layout->latextype != LATEX_ENVIRONMENT) {
131                         // A list-like environment
132                         if (has_item) {
133                                 // a new item. If we had a standard
134                                 // paragraph before, we have to end it.
135                                 if (deeper_paragraph) {
136                                         end_deeper(os);
137                                         deeper_paragraph = false;
138                                 }
139                                 begin_layout(os, layout);
140                                 has_item = false;
141                         } else {
142                                 // a standard paragraph in an
143                                 // enumeration. We have to recognize
144                                 // that this may require a begin_deeper.
145                                 if (!deeper_paragraph)
146                                         begin_deeper(os);
147                                 begin_layout(os, &textclass.defaultLayout());
148                                 deeper_paragraph = true;
149                         }
150                 } else {
151                         // No list-like environment
152                         begin_layout(os, layout);
153                 }
154                 need_layout = false;
155                 need_end_layout = true;
156                 empty = false;
157         }
158 }
159
160
161 void Context::check_end_layout(ostream & os)
162 {
163         if (need_end_layout) {
164                 end_layout(os);
165                 need_end_layout = false;
166         }
167 }
168
169
170 void Context::check_deeper(ostream & os)
171 {
172         if (parent_layout->isEnvironment()) {
173                 // We start a nested environment.
174                 // We need to increase the depth.
175                 if (need_end_deeper) {
176                         // no need to have \end_deeper \begin_deeper
177                         need_end_deeper = false;
178                 } else {
179                         begin_deeper(os);
180                         need_end_deeper = true;
181                 }
182         } else
183                 check_end_deeper(os);
184 }
185
186
187 void Context::check_end_deeper(ostream & os)
188 {
189         if (need_end_deeper) {
190                 end_deeper(os);
191                 need_end_deeper = false;
192         }
193         if (deeper_paragraph) {
194                 end_deeper(os);
195                 deeper_paragraph = false;
196         }
197 }
198
199
200 void Context::set_item()
201 {
202         need_layout = true;
203         has_item = true;
204 }
205
206
207 void Context::new_paragraph(ostream & os)
208 {
209         check_end_layout(os);
210         need_layout = true;
211 }
212
213
214 void Context::add_extra_stuff(string const & stuff)
215 {
216         if (!contains(extra_stuff, stuff))
217                 extra_stuff += stuff;
218 }
219
220
221 void Context::add_par_extra_stuff(string const & stuff)
222 {
223         if (!contains(par_extra_stuff, stuff))
224                 par_extra_stuff += stuff;
225 }
226
227
228 void Context::dump(ostream & os, string const & desc) const
229 {
230         os << "\n" << desc <<" [";
231         if (need_layout)
232                 os << "need_layout ";
233         if (need_end_layout)
234                 os << "need_end_layout ";
235         if (need_end_deeper)
236                 os << "need_end_deeper ";
237         if (has_item)
238                 os << "has_item ";
239         if (deeper_paragraph)
240                 os << "deeper_paragraph ";
241         if (new_layout_allowed)
242                 os << "new_layout_allowed ";
243         if (!extra_stuff.empty())
244                 os << "extrastuff=[" << extra_stuff << "] ";
245         if (!par_extra_stuff.empty())
246                 os << "parextrastuff=[" << par_extra_stuff << "] ";
247         os << "textclass=" << textclass.name()
248            << " layout=" << to_utf8(layout->name())
249            << " parent_layout=" << to_utf8(parent_layout->name()) << "] font=["
250            << font.size << ' ' << font.family << ' ' << font.series << ' '
251            << font.shape << ']' << endl;
252 }
253
254
255 } // namespace lyx