]> git.lyx.org Git - lyx.git/blob - src/tex2lyx/Context.cpp
tex2lyx: improve CJK handling
[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         output_font_change(os, normalfont, font);
117 }
118
119
120 void Context::check_layout(ostream & os)
121 {
122         if (need_layout) {
123                 check_end_layout(os);
124
125                 // are we in a list-like environment?
126                 if (layout->isEnvironment()
127                     && layout->latextype != LATEX_ENVIRONMENT) {
128                         // A list-like environment
129                         if (has_item) {
130                                 // a new item. If we had a standard
131                                 // paragraph before, we have to end it.
132                                 if (deeper_paragraph) {
133                                         end_deeper(os);
134                                         deeper_paragraph = false;
135                                 }
136                                 begin_layout(os, layout);
137                                 has_item = false;
138                         } else {
139                                 // a standard paragraph in an
140                                 // enumeration. We have to recognize
141                                 // that this may require a begin_deeper.
142                                 if (!deeper_paragraph)
143                                         begin_deeper(os);
144                                 begin_layout(os, &textclass.defaultLayout());
145                                 deeper_paragraph = true;
146                         }
147                 } else {
148                         // No list-like environment
149                         begin_layout(os, layout);
150                 }
151                 need_layout = false;
152                 need_end_layout = true;
153                 os << "\n";
154                 empty = false;
155         }
156 }
157
158
159 void Context::check_end_layout(ostream & os)
160 {
161         if (need_end_layout) {
162                 end_layout(os);
163                 need_end_layout = false;
164         }
165 }
166
167
168 void Context::check_deeper(ostream & os)
169 {
170         if (parent_layout->isEnvironment()) {
171                 // We start a nested environment.
172                 // We need to increase the depth.
173                 if (need_end_deeper) {
174                         // no need to have \end_deeper \begin_deeper
175                         need_end_deeper = false;
176                 } else {
177                         begin_deeper(os);
178                         need_end_deeper = true;
179                 }
180         } else
181                 check_end_deeper(os);
182 }
183
184
185 void Context::check_end_deeper(ostream & os)
186 {
187         if (need_end_deeper) {
188                 end_deeper(os);
189                 need_end_deeper = false;
190         }
191         if (deeper_paragraph) {
192                 end_deeper(os);
193                 deeper_paragraph = false;
194         }
195 }
196
197
198 void Context::set_item()
199 {
200         need_layout = true;
201         has_item = true;
202 }
203
204
205 void Context::new_paragraph(ostream & os)
206 {
207         check_end_layout(os);
208         need_layout = true;
209 }
210
211
212 void Context::add_extra_stuff(string const & stuff)
213 {
214         if (!contains(extra_stuff, stuff))
215                 extra_stuff += stuff;
216 }
217
218
219 void Context::add_par_extra_stuff(string const & stuff)
220 {
221         if (!contains(par_extra_stuff, stuff))
222                 par_extra_stuff += stuff;
223 }
224
225
226 void Context::dump(ostream & os, string const & desc) const
227 {
228         os << "\n" << desc <<" [";
229         if (need_layout)
230                 os << "need_layout ";
231         if (need_end_layout)
232                 os << "need_end_layout ";
233         if (need_end_deeper)
234                 os << "need_end_deeper ";
235         if (has_item)
236                 os << "has_item ";
237         if (deeper_paragraph)
238                 os << "deeper_paragraph ";
239         if (new_layout_allowed)
240                 os << "new_layout_allowed ";
241         if (!extra_stuff.empty())
242                 os << "extrastuff=[" << extra_stuff << "] ";
243         if (!par_extra_stuff.empty())
244                 os << "parextrastuff=[" << par_extra_stuff << "] ";
245         os << "textclass=" << textclass.name()
246            << " layout=" << to_utf8(layout->name())
247            << " parent_layout=" << to_utf8(parent_layout->name()) << "] font=["
248            << font.size << ' ' << font.family << ' ' << font.series << ' '
249            << font.shape << ']' << endl;
250 }
251
252
253 } // namespace lyx