]> git.lyx.org Git - lyx.git/blob - src/insets/insetminipage.C
the string -> char patch
[lyx.git] / src / insets / insetminipage.C
1 /**
2  * \file insetminipage.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna
7  * \author Lars Gullik Bjønnes
8  *
9  * Full author contact details are available in file CREDITS
10  */
11
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "insetminipage.h"
19 #include "gettext.h"
20 #include "lyxfont.h"
21 #include "BufferView.h"
22 #include "frontends/LyXView.h"
23 #include "frontends/Dialogs.h"
24 #include "lyxtext.h"
25 #include "insets/insettext.h"
26 #include "support/LOstream.h"
27 #include "support/lstrings.h"
28 #include "debug.h"
29 #include "gettext.h"
30 #include "lyxlex.h"
31
32 using std::ostream;
33 using std::endl;
34
35
36 // Some information about Minipages in LaTeX:
37 // A minipage is a complete miniversion of a page and can contain
38 // its own footnotes, paragraphs, and array, tabular, and multicols
39 // environments. However it cannot contain floats or \marginpar's,
40 // but it can appear inside floats.
41 //
42 // The minipage environment is defined like this:
43 //
44 // \begin{minipage}[pos][height][inner-pos]{width} <text> \end{minipage}
45 //
46 // Where:
47 //     pos [opt] = is the vertical placement of the box with respect
48 //                 to the text baseline, [c], [t] and [b].
49 //     height [opt] = the height of the box
50 //     inner-pos [opt] = the position of the text within the box.
51 //                 It can be t, c, b or s, if unspecified the value
52 //                 of pos is used.
53 //     width = the width of the box
54 //
55 // In LyX we should try to support all these parameters, settable in a
56 // pop-up dialog.
57 // In this pop-up diallog it should also be possible to set all margin
58 // values that is usable in the minipage.
59 // With regard to different formats (like DocBook) I guess a minipage
60 // can be used there also. Perhaps not in the latex way, but we do not
61 // have to output "" for minipages.
62 // (Lgb)
63
64 InsetMinipage::InsetMinipage(BufferParams const & bp)
65         : InsetCollapsable(bp), pos_(center),
66           inner_pos_(inner_center), width_(100, LyXLength::PCW)
67 {
68         setLabel(_("minipage"));
69         LyXFont font(LyXFont::ALL_SANE);
70         font.decSize();
71         font.decSize();
72         font.setColor(LColor::collapsable);
73         setLabelFont(font);
74 #if 0
75         setAutoCollapse(false);
76 #endif
77
78 #if 0
79 #ifdef WITH_WARNINGS
80 #warning Remove this color definitions before 1.2.0 final!
81 #endif
82         // just for experimentation :)
83         setBackgroundColor(LColor::green);
84 #endif
85
86         inset.setFrameColor(0, LColor::blue);
87         setInsetName("Minipage");
88 }
89
90
91 InsetMinipage::InsetMinipage(InsetMinipage const & in, bool same_id)
92         : InsetCollapsable(in, same_id),
93           pos_(in.pos_), inner_pos_(in.inner_pos_),
94           height_(in.height_), width_(in.width_)
95 {}
96
97
98 Inset * InsetMinipage::clone(Buffer const &, bool same_id) const
99 {
100         return new InsetMinipage(*const_cast<InsetMinipage *>(this), same_id);
101 }
102
103
104 InsetMinipage::~InsetMinipage()
105 {
106         hideDialog();
107 }
108
109
110 void InsetMinipage::write(Buffer const * buf, ostream & os) const
111 {
112         os << getInsetName() << '\n'
113            << "position " << pos_ << '\n'
114            << "inner_position " << inner_pos_ << '\n'
115            << "height \"" << height_.asString() << "\"\n"
116            << "width \"" << width_.asString() << "\"\n";
117         InsetCollapsable::write(buf, os);
118 }
119
120
121 void InsetMinipage::read(Buffer const * buf, LyXLex & lex)
122 {
123         if (lex.isOK()) {
124                 lex.next();
125                 string const token = lex.getString();
126                 if (token == "position") {
127                         lex.next();
128                         pos_ = static_cast<Position>(lex.getInteger());
129                 } else {
130                         lyxerr << "InsetMinipage::Read: Missing 'position'-tag!"
131                                    << endl;
132                         // take countermeasures
133                         lex.pushToken(token);
134                 }
135         }
136         if (lex.isOK()) {
137                 lex.next();
138                 string const token = lex.getString();
139                 if (token == "inner_position") {
140                         lex.next();
141                         inner_pos_ = static_cast<InnerPosition>(lex.getInteger());
142                 } else {
143                         lyxerr << "InsetMinipage::Read: Missing 'inner_position'-tag!"
144                                    << endl;
145                         // take countermeasures
146                         lex.pushToken(token);
147                 }
148         }
149         if (lex.isOK()) {
150                 lex.next();
151                 string const token = lex.getString();
152                 if (token == "height") {
153                         lex.next();
154                         height_ = LyXLength(lex.getString());
155                 } else {
156                         lyxerr << "InsetMinipage::Read: Missing 'height'-tag!"
157                                    << endl;
158                         // take countermeasures
159                         lex.pushToken(token);
160                 }
161         }
162         if (lex.isOK()) {
163                 lex.next();
164                 string const token = lex.getString();
165                 if (token == "width") {
166                         lex.next();
167                         width_ = LyXLength(lex.getString());
168                 } else {
169                         lyxerr << "InsetMinipage::Read: Missing 'width'-tag!"
170                                    << endl;
171                         // take countermeasures
172                         lex.pushToken(token);
173                 }
174         }
175         InsetCollapsable::read(buf, lex);
176 }
177
178
179 int InsetMinipage::ascent(BufferView * bv, LyXFont const & font) const
180 {
181         if (collapsed_)
182                 return ascent_collapsed();
183         else {
184                 // Take placement into account.
185                 int i = 0;
186                 switch (pos_) {
187                 case top:
188                         i = InsetCollapsable::ascent(bv, font);
189                         break;
190                 case center:
191                         i = (InsetCollapsable::ascent(bv, font)
192                              + InsetCollapsable::descent(bv, font)) / 2;
193                         break;
194                 case bottom:
195                         i = InsetCollapsable::descent(bv, font);
196                         break;
197                 }
198                 return i;
199         }
200 }
201
202
203 int InsetMinipage::descent(BufferView * bv, LyXFont const & font) const
204 {
205         if (collapsed_)
206                 return descent_collapsed();
207         else {
208                 // Take placement into account.
209                 int i = 0;
210                 switch (pos_) {
211                 case top:
212                         i = InsetCollapsable::descent(bv, font);
213                         break;
214                 case center:
215                         i = (InsetCollapsable::ascent(bv, font)
216                              + InsetCollapsable::descent(bv, font)) / 2;
217                         break;
218                 case bottom:
219                         i = InsetCollapsable::ascent(bv, font);
220                         break;
221                 }
222                 return i;
223         }
224 }
225
226
227 string const InsetMinipage::editMessage() const
228 {
229         return _("Opened Minipage Inset");
230 }
231
232
233 int InsetMinipage::latex(Buffer const * buf,
234                          ostream & os, bool fragile, bool fp) const
235 {
236         string s_pos;
237         switch (pos_) {
238         case top:
239                 s_pos += 't';
240                 break;
241         case center:
242                 s_pos += 'c';
243                 break;
244         case bottom:
245                 s_pos += 'b';
246                 break;
247         }
248         os << "\\begin{minipage}[" << s_pos << "]{"
249            << width_.asLatexString() << "}%\n";
250
251         int i = inset.latex(buf, os, fragile, fp);
252
253         os << "\\end{minipage}%\n";
254         return i + 2;
255 }
256
257
258 bool InsetMinipage::insetAllowed(Inset::Code code) const
259 {
260         if ((code == Inset::FLOAT_CODE) || (code == Inset::MARGIN_CODE))
261                 return false;
262
263         return InsetCollapsable::insetAllowed(code);
264 }
265
266
267 InsetMinipage::Position InsetMinipage::pos() const
268 {
269         return pos_;
270 }
271
272
273 void InsetMinipage::pos(InsetMinipage::Position p)
274 {
275         if (pos_ != p) {
276                 pos_ = p;
277                 need_update = FULL;
278         }
279 }
280
281
282 InsetMinipage::InnerPosition InsetMinipage::innerPos() const
283 {
284         return inner_pos_;
285 }
286
287
288 void InsetMinipage::innerPos(InsetMinipage::InnerPosition ip)
289 {
290         inner_pos_ = ip;
291 }
292
293
294 LyXLength const & InsetMinipage::pageHeight() const
295 {
296         return height_;
297 }
298
299
300 void InsetMinipage::pageHeight(LyXLength const & ll)
301 {
302         if (height_ != ll) {
303                 height_ = ll;
304                 need_update = FULL;
305         }
306 }
307
308
309 LyXLength const & InsetMinipage::pageWidth() const
310 {
311         return width_;
312 }
313
314
315 void InsetMinipage::pageWidth(LyXLength const & ll)
316 {
317         if (ll != width_) {
318                 width_ = ll;
319                 need_update = FULL;
320         }
321 }
322
323
324 bool InsetMinipage::showInsetDialog(BufferView * bv) const
325 {
326         if (!inset.showInsetDialog(bv))
327                 bv->owner()->getDialogs().showMinipage(const_cast<InsetMinipage *>(this));
328         return true;
329 }
330
331
332 int InsetMinipage::getMaxWidth(BufferView * bv, UpdatableInset const * inset)
333         const
334 {
335         if (owner() &&
336             static_cast<UpdatableInset*>(owner())->getMaxWidth(bv, inset) < 0) {
337                 return -1;
338         }
339         if (!width_.zero()) {
340                 int ww1 = latexTextWidth(bv);
341                 int ww2 = InsetCollapsable::getMaxWidth(bv, inset);
342                 if (ww2 > 0 && ww2 < ww1) {
343                         return ww2;
344                 }
345                 return ww1;
346         }
347         // this should not happen!
348         return InsetCollapsable::getMaxWidth(bv, inset);
349 }
350
351
352 int InsetMinipage::latexTextWidth(BufferView * bv) const
353 {
354         return width_.inPixels(InsetCollapsable::latexTextWidth(bv));
355 }