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