]> git.lyx.org Git - lyx.git/blob - src/tex2lyx/Context.cpp
Fix #10778 (issue with CJK and language nesting)
[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), merging_hyphens_allowed(true),
86           textclass(textclass_),
87           layout(layout_), parent_layout(parent_layout_),
88           font(font_)
89 {
90         if (!layout)
91                 layout = &textclass.defaultLayout();
92         if (!parent_layout)
93                 parent_layout = &textclass.defaultLayout();
94 }
95
96
97 Context::~Context()
98 {
99         if (!par_extra_stuff.empty())
100                 cerr << "Bug: Ignoring par-level extra stuff '"
101                      << par_extra_stuff << '\'' << endl;
102 }
103
104
105 void Context::begin_layout(ostream & os, Layout const * const & l)
106 {
107         os << "\n\\begin_layout " << to_utf8(l->name()) << "\n";
108         if (!extra_stuff.empty()) {
109                 os << extra_stuff;
110         }
111         if (!par_extra_stuff.empty()) {
112                 os << par_extra_stuff;
113                 par_extra_stuff.erase();
114         }
115         // FIXME: This is not enough for things like
116         // \\Huge par1 \\par par2
117         // FIXME: If the document language is not english this outputs a
118         // superflous language change. Fortunately this is only file format
119         // bloat and does not change the TeX export of LyX.
120         output_font_change(os, normalfont, font);
121 }
122
123
124 void Context::check_layout(ostream & os)
125 {
126         if (need_layout) {
127                 check_end_layout(os);
128
129                 // are we in a list-like environment?
130                 if (layout->isEnvironment()
131                     && layout->latextype != LATEX_ENVIRONMENT) {
132                         // A list-like environment
133                         if (has_item) {
134                                 // a new item. If we had a standard
135                                 // paragraph before, we have to end it.
136                                 if (deeper_paragraph) {
137                                         end_deeper(os);
138                                         deeper_paragraph = false;
139                                 }
140                                 begin_layout(os, layout);
141                                 has_item = false;
142                         } else {
143                                 // a standard paragraph in an
144                                 // enumeration. We have to recognize
145                                 // that this may require a begin_deeper.
146                                 if (!deeper_paragraph)
147                                         begin_deeper(os);
148                                 begin_layout(os, &textclass.defaultLayout());
149                                 deeper_paragraph = true;
150                         }
151                 } else {
152                         // No list-like environment
153                         begin_layout(os, layout);
154                 }
155                 need_layout = false;
156                 need_end_layout = true;
157                 empty = false;
158         }
159 }
160
161
162 void Context::check_end_layout(ostream & os)
163 {
164         if (need_end_layout) {
165                 end_layout(os);
166                 need_end_layout = false;
167         }
168 }
169
170
171 void Context::check_deeper(ostream & os)
172 {
173         if (parent_layout->isEnvironment()) {
174                 // We start a nested environment.
175                 // We need to increase the depth.
176                 if (need_end_deeper) {
177                         // no need to have \end_deeper \begin_deeper
178                         need_end_deeper = false;
179                 } else {
180                         begin_deeper(os);
181                         need_end_deeper = true;
182                 }
183         } else
184                 check_end_deeper(os);
185 }
186
187
188 void Context::check_end_deeper(ostream & os)
189 {
190         if (need_end_deeper) {
191                 end_deeper(os);
192                 need_end_deeper = false;
193         }
194         if (deeper_paragraph) {
195                 end_deeper(os);
196                 deeper_paragraph = false;
197         }
198 }
199
200
201 void Context::set_item()
202 {
203         need_layout = true;
204         has_item = true;
205 }
206
207
208 void Context::new_paragraph(ostream & os)
209 {
210         check_end_layout(os);
211         need_layout = true;
212 }
213
214
215 void Context::add_extra_stuff(string const & stuff)
216 {
217         if (!contains(extra_stuff, stuff))
218                 extra_stuff += stuff;
219 }
220
221
222 void Context::add_par_extra_stuff(string const & stuff)
223 {
224         if (!contains(par_extra_stuff, stuff))
225                 par_extra_stuff += stuff;
226 }
227
228
229 void Context::dump(ostream & os, string const & desc) const
230 {
231         os << "\n" << desc <<" [";
232         if (need_layout)
233                 os << "need_layout ";
234         if (need_end_layout)
235                 os << "need_end_layout ";
236         if (need_end_deeper)
237                 os << "need_end_deeper ";
238         if (has_item)
239                 os << "has_item ";
240         if (deeper_paragraph)
241                 os << "deeper_paragraph ";
242         if (new_layout_allowed)
243                 os << "new_layout_allowed ";
244         if (merging_hyphens_allowed)
245                 os << "merging_hyphens_allowed ";
246         if (!extra_stuff.empty())
247                 os << "extrastuff=[" << extra_stuff << "] ";
248         if (!par_extra_stuff.empty())
249                 os << "parextrastuff=[" << par_extra_stuff << "] ";
250         os << "textclass=" << textclass.name()
251            << " layout=" << to_utf8(layout->name())
252            << " parent_layout=" << to_utf8(parent_layout->name()) << "] font=["
253            << font.size << ' ' << font.family << ' ' << font.series << ' '
254            << font.shape << ']' << endl;
255 }
256
257
258 } // namespace lyx