]> git.lyx.org Git - lyx.git/blob - src/insets/InsetNewpage.cpp
Move Lexer to support/ directory (and lyx::support namespace)
[lyx.git] / src / insets / InsetNewpage.cpp
1 /**
2  * \file InsetNewpage.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetNewpage.h"
15
16 #include "Cursor.h"
17 #include "FuncRequest.h"
18 #include "FuncStatus.h"
19 #include "MetricsInfo.h"
20 #include "xml.h"
21 #include "texstream.h"
22 #include "Text.h"
23 #include "TextMetrics.h"
24
25 #include "frontends/FontMetrics.h"
26 #include "frontends/Painter.h"
27
28 #include "support/debug.h"
29 #include "support/docstring.h"
30 #include "support/docstream.h"
31 #include "support/gettext.h"
32 #include "support/Lexer.h"
33
34 using namespace std;
35
36 namespace lyx {
37
38 using support::Lexer;
39
40 InsetNewpage::InsetNewpage() : Inset(nullptr)
41 {}
42
43
44 InsetNewpage::InsetNewpage(InsetNewpageParams const & params)
45         : Inset(nullptr), params_(params)
46 {}
47
48
49 void InsetNewpageParams::write(ostream & os) const
50 {
51         switch (kind) {
52         case InsetNewpageParams::NEWPAGE:
53                 os << "newpage";
54                 break;
55         case InsetNewpageParams::PAGEBREAK:
56                 os <<  "pagebreak";
57                 break;
58         case InsetNewpageParams::CLEARPAGE:
59                 os <<  "clearpage";
60                 break;
61         case InsetNewpageParams::CLEARDOUBLEPAGE:
62                 os <<  "cleardoublepage";
63                 break;
64         case InsetNewpageParams::NOPAGEBREAK:
65                 os <<  "nopagebreak";
66                 break;
67         }
68 }
69
70
71 void InsetNewpageParams::read(Lexer & lex)
72 {
73         lex.setContext("InsetNewpageParams::read");
74         string token;
75         lex >> token;
76
77         if (token == "newpage")
78                 kind = InsetNewpageParams::NEWPAGE;
79         else if (token == "pagebreak")
80                 kind = InsetNewpageParams::PAGEBREAK;
81         else if (token == "clearpage")
82                 kind = InsetNewpageParams::CLEARPAGE;
83         else if (token == "cleardoublepage")
84                 kind = InsetNewpageParams::CLEARDOUBLEPAGE;
85         else if (token == "nopagebreak")
86                 kind = InsetNewpageParams::NOPAGEBREAK;
87         else
88                 lex.printError("Unknown kind");
89 }
90
91
92 void InsetNewpage::write(ostream & os) const
93 {
94         os << "Newpage ";
95         params_.write(os);
96 }
97
98
99 void InsetNewpage::read(Lexer & lex)
100 {
101         params_.read(lex);
102         lex >> "\\end_inset";
103 }
104
105
106 void InsetNewpage::metrics(MetricsInfo & mi, Dimension & dim) const
107 {
108         if (params_.kind == InsetNewpageParams::NOPAGEBREAK) {
109                 frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
110                 dim.asc = fm.maxAscent();
111                 dim.des = fm.maxDescent();
112                 dim.wid = 3 * fm.width('n');
113                 return;
114         }
115
116         dim.asc = defaultRowHeight();
117         dim.des = defaultRowHeight();
118         dim.wid = mi.base.textwidth;
119 }
120
121
122 void InsetNewpage::draw(PainterInfo & pi, int x, int y) const
123 {
124         if (params_.kind == InsetNewpageParams::NOPAGEBREAK) {
125
126                 FontInfo font;
127                 font.setColor(ColorName());
128
129                 frontend::FontMetrics const & fm = theFontMetrics(pi.base.font);
130                 int const wid = 3 * fm.width('n');
131                 int const asc = fm.maxAscent();
132
133                 int xp[3];
134                 int yp[3];
135
136                 //left side arrow
137                 yp[0] = int(y - 0.875 * asc * 0.75);
138                 yp[1] = int(y - 0.500 * asc * 0.75);
139                 yp[2] = int(y - 0.125 * asc * 0.75);
140                 xp[0] = int(x + wid * 0.25);
141                 xp[1] = int(x + wid * 0.4); 
142                 xp[2] = int(x + wid * 0.25);
143                 pi.pain.lines(xp, yp, 3, ColorName());
144
145                 yp[0] = yp[1] = int(y - 0.500 * asc * 0.75);
146                 xp[0] = int(x + wid * 0.03);
147                 xp[1] = int(x + wid * 0.4); 
148                 pi.pain.lines(xp, yp, 2, ColorName());
149
150                 //right side arrow
151                 yp[0] = int(y - 0.875 * asc * 0.75);
152                 yp[1] = int(y - 0.500 * asc * 0.75);
153                 yp[2] = int(y - 0.125 * asc * 0.75);
154                 xp[0] = int(x + wid * 0.75);
155                 xp[1] = int(x + wid * 0.6); 
156                 xp[2] = int(x + wid * 0.75);
157                 pi.pain.lines(xp, yp, 3, ColorName());
158
159                 yp[0] = yp[1] = int(y - 0.500 * asc * 0.75);
160                 xp[0] = int(x + wid * 0.97);
161                 xp[1] = int(x + wid * 0.6); 
162                 pi.pain.lines(xp, yp, 2, ColorName());
163
164                 //mid-rule
165                 xp[0] = xp[1] = int(x + wid * 0.5);
166                 yp[0] = int(y - 0.875 * asc * 0.75);
167                 yp[1] = int(y - 0.125 * asc * 0.75);
168                 pi.pain.lines(xp, yp, 2, ColorName());
169                 return;
170         }
171
172         using frontend::Painter;
173
174         FontInfo font;
175         font.setColor(ColorName());
176         font.decSize();
177
178         Dimension const dim = dimension(*pi.base.bv);
179
180         int w = 0;
181         int a = 0;
182         int d = 0;
183         theFontMetrics(font).rectText(insetLabel(), w, a, d);
184
185         int const text_start = int(x + (dim.wid - w) / 2);
186         int const text_end = text_start + w;
187
188         pi.pain.rectText(text_start, y + d, insetLabel(), font,
189                 Color_none, Color_none);
190
191         pi.pain.line(x, y, text_start, y,
192                    ColorName(), Painter::line_onoffdash);
193         pi.pain.line(text_end, y, int(x + dim.wid), y,
194                    ColorName(), Painter::line_onoffdash);
195 }
196
197
198 void InsetNewpage::doDispatch(Cursor & cur, FuncRequest & cmd)
199 {
200         switch (cmd.action()) {
201
202         case LFUN_INSET_MODIFY: {
203                 InsetNewpageParams params;
204                 cur.recordUndo();
205                 string2params(to_utf8(cmd.argument()), params);
206                 params_.kind = params.kind;
207                 break;
208         }
209
210         default:
211                 Inset::doDispatch(cur, cmd);
212                 break;
213         }
214 }
215
216
217 bool InsetNewpage::getStatus(Cursor & cur, FuncRequest const & cmd,
218         FuncStatus & status) const
219 {
220         switch (cmd.action()) {
221         // we handle these
222         case LFUN_INSET_MODIFY:
223                 if (cmd.getArg(0) == "newpage") {
224                         InsetNewpageParams params;
225                         string2params(to_utf8(cmd.argument()), params);
226                         status.setOnOff(params_.kind == params.kind);
227                 }
228                 status.setEnabled(true);
229                 return true;
230         default:
231                 return Inset::getStatus(cur, cmd, status);
232         }
233 }
234
235
236 docstring InsetNewpage::insetLabel() const
237 {
238         switch (params_.kind) {
239                 case InsetNewpageParams::NEWPAGE:
240                         return _("New Page");
241                 case InsetNewpageParams::PAGEBREAK:
242                         return _("Page Break");
243                 case InsetNewpageParams::CLEARPAGE:
244                         return _("Clear Page");
245                 case InsetNewpageParams::CLEARDOUBLEPAGE:
246                         return _("Clear Double Page");
247                 case InsetNewpageParams::NOPAGEBREAK:
248                         return _("No Page Break");
249                 default:
250                         return _("New Page");
251         }
252 }
253
254
255 ColorCode InsetNewpage::ColorName() const
256 {
257         switch (params_.kind) {
258                 case InsetNewpageParams::PAGEBREAK:
259                 case InsetNewpageParams::NOPAGEBREAK:
260                         return Color_pagebreak;
261                 case InsetNewpageParams::NEWPAGE:
262                 case InsetNewpageParams::CLEARPAGE:
263                 case InsetNewpageParams::CLEARDOUBLEPAGE:
264                         return Color_newpage;
265         }
266         // not really useful, but to avoids gcc complaints
267         return Color_newpage;
268 }
269
270
271 void InsetNewpage::latex(otexstream & os, OutputParams const & runparams) const
272 {
273         if (runparams.inDeletedInset) {
274                 os << "\\mbox{}\\\\\\makebox[\\columnwidth]{\\dotfill\\ "
275                    << insetLabel() << "\\ \\dotfill}";
276         } else {
277                 switch (params_.kind) {
278                 case InsetNewpageParams::NEWPAGE:
279                         os << "\\newpage" << termcmd;
280                         break;
281                 case InsetNewpageParams::PAGEBREAK:
282                         if (runparams.moving_arg)
283                                 os << "\\protect";
284                         os << "\\pagebreak" << termcmd;
285                         break;
286                 case InsetNewpageParams::CLEARPAGE:
287                         os << "\\clearpage" << termcmd;
288                         break;
289                 case InsetNewpageParams::CLEARDOUBLEPAGE:
290                         os << "\\cleardoublepage" << termcmd;
291                         break;
292                 case InsetNewpageParams::NOPAGEBREAK:
293                         os << "\\nopagebreak" << termcmd;
294                         break;
295                 default:
296                         os << "\\newpage" << termcmd;
297                         break;
298                 }
299         }
300 }
301
302
303 int InsetNewpage::plaintext(odocstringstream & os,
304         OutputParams const &, size_t) const
305 {
306         if (params_.kind ==  InsetNewpageParams::NOPAGEBREAK)
307                 return 0;
308         os << '\n';
309         return PLAINTEXT_NEWLINE;
310 }
311
312
313 void InsetNewpage::docbook(XMLStream & os, OutputParams const &) const
314 {
315         if (params_.kind !=  InsetNewpageParams::NOPAGEBREAK)
316                 os << xml::CR();
317 }
318
319
320 docstring InsetNewpage::xhtml(XMLStream & xs, OutputParams const &) const
321 {
322         if (params_.kind !=  InsetNewpageParams::NOPAGEBREAK)
323                 xs << xml::CompTag("br");
324         return docstring();
325 }
326
327
328 string InsetNewpage::contextMenuName() const
329 {
330         return "context-newpage";
331 }
332
333
334 void InsetNewpage::string2params(string const & in, InsetNewpageParams & params)
335 {
336         params = InsetNewpageParams();
337         if (in.empty())
338                 return;
339
340         istringstream data(in);
341         Lexer lex;
342         lex.setStream(data);
343
344         string name;
345         lex >> name;
346         if (!lex || name != "newpage") {
347                 LYXERR0("Expected arg 2 to be \"wrap\" in " << in);
348                 return;
349         }
350
351         params.read(lex);
352 }
353
354
355 string InsetNewpage::params2string(InsetNewpageParams const & params)
356 {
357         ostringstream data;
358         data << "newpage" << ' ';
359         params.write(data);
360         return data.str();
361 }
362
363
364 } // namespace lyx