]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
647760723503eb28db6f5829340b1f9b4839b60a
[lyx.git] / src / insets / insetert.C
1 /**
2  * \file insetert.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 #include "insetert.h"
15
16 #include "buffer.h"
17 #include "bufferparams.h"
18 #include "BufferView.h"
19 #include "cursor.h"
20 #include "debug.h"
21 #include "dispatchresult.h"
22 #include "funcrequest.h"
23 #include "FuncStatus.h"
24 #include "gettext.h"
25 #include "language.h"
26 #include "LColor.h"
27 #include "LyXAction.h"
28 #include "lyxlex.h"
29 #include "lyxtextclass.h"
30 #include "metricsinfo.h"
31 #include "ParagraphParameters.h"
32 #include "paragraph.h"
33
34 #include "frontends/Alert.h"
35 #include "frontends/LyXView.h"
36
37 #include <sstream>
38
39 using lyx::pos_type;
40 using lyx::support::token;
41
42 using std::endl;
43 using std::min;
44
45 using std::auto_ptr;
46 using std::istringstream;
47 using std::ostream;
48 using std::ostringstream;
49 using std::string;
50
51
52 void InsetERT::init()
53 {
54         setButtonLabel();
55
56         LyXFont font(LyXFont::ALL_SANE);
57         font.decSize();
58         font.decSize();
59         font.setColor(LColor::latex);
60         setLabelFont(font);
61         text_.current_font.setLanguage(latex_language);
62         text_.real_current_font.setLanguage(latex_language);
63
64         setInsetName("ERT");
65 }
66
67
68 InsetERT::InsetERT(BufferParams const & bp, CollapseStatus status)
69         : InsetCollapsable(bp, status)
70 {
71         init();
72 }
73
74
75 InsetERT::InsetERT(InsetERT const & in)
76         : InsetCollapsable(in)
77 {
78         init();
79 }
80
81
82 auto_ptr<InsetBase> InsetERT::doClone() const
83 {
84         return auto_ptr<InsetBase>(new InsetERT(*this));
85 }
86
87
88 #if 0
89 InsetERT::InsetERT(BufferParams const & bp,
90                    Language const *, string const & contents, CollapseStatus status)
91         : InsetCollapsable(bp, status)
92 {
93         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
94         paragraphs().begin()->insert(0, contents, font);
95
96         // the init has to be after the initialization of the paragraph
97         // because of the label settings (draw_label for ert insets).
98         init();
99 }
100 #endif
101
102
103 InsetERT::~InsetERT()
104 {
105         InsetERTMailer(*this).hideDialog();
106 }
107
108
109 void InsetERT::write(Buffer const & buf, ostream & os) const
110 {
111         os << "ERT" << "\n";
112         InsetCollapsable::write(buf, os);
113 }
114
115
116 void InsetERT::read(Buffer const & buf, LyXLex & lex)
117 {
118         InsetCollapsable::read(buf, lex);
119
120         // Force default font
121         // This avoids paragraphs in buffer language that would have a
122         // foreign language after a document langauge change, and it ensures
123         // that all new text in ERT gets the "latex" language, since new text
124         // inherits the language from the last position of the existing text.
125         // As a side effect this makes us also robust against bugs in LyX
126         // that might lead to font changes in ERT in .lyx files.
127         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
128         ParagraphList::iterator par = paragraphs().begin();
129         ParagraphList::iterator const end = paragraphs().end();
130         while (par != end) {
131                 pos_type siz = par->size();
132                 for (pos_type i = 0; i <= siz; ++i) {
133                         par->setFont(i, font);
134                 }
135                 ++par;
136         }
137 }
138
139
140 string const InsetERT::editMessage() const
141 {
142         return _("Opened ERT Inset");
143 }
144
145
146 int InsetERT::latex(Buffer const &, ostream & os,
147                     OutputParams const &) const
148 {
149         ParagraphList::const_iterator par = paragraphs().begin();
150         ParagraphList::const_iterator end = paragraphs().end();
151
152         int lines = 0;
153         while (par != end) {
154                 pos_type siz = par->size();
155                 for (pos_type i = 0; i < siz; ++i) {
156                         // ignore all struck out text
157                         if (isDeletedText(*par, i))
158                                 continue;
159
160                         os << par->getChar(i);
161                 }
162                 ++par;
163                 if (par != end) {
164                         os << "\n";
165                         ++lines;
166                 }
167         }
168
169         return lines;
170 }
171
172
173 int InsetERT::plaintext(Buffer const &, ostream &,
174                     OutputParams const & /*runparams*/) const
175 {
176         return 0;
177 }
178
179
180 int InsetERT::linuxdoc(Buffer const &, ostream & os,
181                        OutputParams const &) const
182 {
183         ParagraphList::const_iterator par = paragraphs().begin();
184         ParagraphList::const_iterator end = paragraphs().end();
185
186         int lines = 0;
187         while (par != end) {
188                 pos_type siz = par->size();
189                 for (pos_type i = 0; i < siz; ++i)
190                         os << par->getChar(i);
191                 ++par;
192                 if (par != end) {
193                         os << "\n";
194                         lines ++;
195                 }
196         }
197
198         return lines;
199 }
200
201
202 int InsetERT::docbook(Buffer const &, ostream & os,
203                       OutputParams const &) const
204 {
205         ParagraphList::const_iterator par = paragraphs().begin();
206         ParagraphList::const_iterator end = paragraphs().end();
207
208         int lines = 0;
209         while (par != end) {
210                 pos_type siz = par->size();
211                 for (pos_type i = 0; i < siz; ++i)
212                         os << par->getChar(i);
213                 ++par;
214                 if (par != end) {
215                         os << "\n";
216                         ++lines;
217                 }
218         }
219
220         return lines;
221 }
222
223
224 void InsetERT::doDispatch(LCursor & cur, FuncRequest & cmd)
225 {
226         //lyxerr << "\nInsetERT::doDispatch (begin): cmd: " << cmd << endl;
227         switch (cmd.action) {
228
229         case LFUN_INSET_MODIFY: {
230                 InsetCollapsable::CollapseStatus st;
231                 InsetERTMailer::string2params(cmd.argument, st);
232                 setStatus(cur, st);
233                 break;
234         }
235         case LFUN_PASTE:
236         case LFUN_PASTESELECTION: {
237                 InsetCollapsable::doDispatch(cur, cmd);
238
239                 // Since we can only store plain text, we must reset all
240                 // attributes.
241                 // FIXME: Change only the pasted paragraphs
242
243                 BufferParams const & bp = cur.buffer().params();
244                 LyXLayout_ptr const layout =
245                         bp.getLyXTextClass().defaultLayout();
246                 LyXFont font = layout->font;
247                 // ERT contents has always latex_language
248                 font.setLanguage(latex_language);
249                 ParagraphList::iterator const end = paragraphs().end();
250                 for (ParagraphList::iterator par = paragraphs().begin();
251                      par != end; ++par) {
252                         par->layout(layout);
253                         // in case par had a manual label
254                         par->setBeginOfBody();
255                         pos_type const siz = par->size();
256                         for (pos_type i = 0; i < siz; ++i) {
257                                 par->setFont(i, font);
258                         }
259                         par->params().clear();
260                 }
261                 break;
262         }
263         default:
264                 // Force any new text to latex_language
265                 // FIXME: This should only be necessary in init(), but
266                 // new paragraphs that are created by pressing enter at the
267                 // start of an existing paragraph get the buffer language
268                 // and not latex_language, so we take this brute force
269                 // approach.
270                 text_.current_font.setLanguage(latex_language);
271                 text_.real_current_font.setLanguage(latex_language);
272
273                 InsetCollapsable::doDispatch(cur, cmd);
274                 break;
275         }
276 }
277
278
279 bool InsetERT::getStatus(LCursor & cur, FuncRequest const & cmd,
280         FuncStatus & status) const
281 {
282         switch (cmd.action) {
283                 // suppress these
284                 case LFUN_ACUTE:
285                 case LFUN_BREVE:
286                 case LFUN_CARON:
287                 case LFUN_CEDILLA:
288                 case LFUN_CIRCLE:
289                 case LFUN_CIRCUMFLEX:
290                 case LFUN_DOT:
291                 case LFUN_GRAVE:
292                 case LFUN_HUNG_UMLAUT:
293                 case LFUN_MACRON:
294                 case LFUN_OGONEK:
295                 case LFUN_SPECIAL_CARON:
296                 case LFUN_TIE:
297                 case LFUN_TILDE:
298                 case LFUN_UMLAUT:
299                 case LFUN_UNDERBAR:
300                 case LFUN_UNDERDOT:
301                 case LFUN_APPENDIX:
302                 case LFUN_BREAKLINE:
303                 case LFUN_INSET_CAPTION:
304                 case LFUN_DEPTH_MIN:
305                 case LFUN_DEPTH_PLUS:
306                 case LFUN_LDOTS:
307                 case LFUN_END_OF_SENTENCE:
308                 case LFUN_ENVIRONMENT_INSERT:
309                 case LFUN_INSET_ERT:
310                 case LFUN_FILE_INSERT:
311                 case LFUN_INSET_FLOAT:
312                 case LFUN_INSET_WIDE_FLOAT:
313                 case LFUN_INSET_WRAP:
314                 case LFUN_BOLD:
315                 case LFUN_CODE:
316                 case LFUN_DEFAULT:
317                 case LFUN_EMPH:
318                 case LFUN_FREEFONT_APPLY:
319                 case LFUN_FREEFONT_UPDATE:
320                 case LFUN_NOUN:
321                 case LFUN_ROMAN:
322                 case LFUN_SANS:
323                 case LFUN_FRAK:
324                 case LFUN_ITAL:
325                 case LFUN_FONT_SIZE:
326                 case LFUN_FONT_STATE:
327                 case LFUN_UNDERLINE:
328                 case LFUN_INSET_FOOTNOTE:
329                 case LFUN_HFILL:
330                 case LFUN_HTMLURL:
331                 case LFUN_HYPHENATION:
332                 case LFUN_LIGATURE_BREAK:
333                 case LFUN_INDEX_INSERT:
334                 case LFUN_INDEX_PRINT:
335                 case LFUN_INSERT_LABEL:
336                 case LFUN_INSET_OPTARG:
337                 case LFUN_INSERT_BIBITEM:
338                 case LFUN_INSERT_LINE:
339                 case LFUN_INSERT_PAGEBREAK:
340                 case LFUN_LANGUAGE:
341                 case LFUN_LAYOUT:
342                 case LFUN_LAYOUT_PARAGRAPH:
343                 case LFUN_LAYOUT_TABULAR:
344                 case LFUN_INSET_MARGINAL:
345                 case LFUN_MATH_DISPLAY:
346                 case LFUN_INSERT_MATH:
347                 case LFUN_INSERT_MATRIX:
348                 case LFUN_MATH_MODE:
349                 case LFUN_MENU_OPEN_BY_NAME:
350                 case LFUN_MENU_SEPARATOR:
351                 case LFUN_INSERT_BRANCH:
352                 case LFUN_INSERT_CHARSTYLE:
353                 case LFUN_INSERT_NOTE:
354                 case LFUN_INSERT_BOX:
355                 case LFUN_GOTONOTE:
356                 case LFUN_PARAGRAPH_SPACING:
357                 case LFUN_QUOTE:
358                 case LFUN_LABEL_GOTO:
359                 case LFUN_REFERENCE_GOTO:
360                 case LFUN_SPACE_INSERT:
361                 case LFUN_GOTOFILEROW:
362                 case LFUN_NOTIFY:
363                 case LFUN_SETXY:
364                 case LFUN_TABULAR_INSERT:
365                 case LFUN_TOC_INSERT:
366                 case LFUN_URL:
367                 case LFUN_FLOAT_LIST:
368                 case LFUN_INSET_INSERT:
369                 case LFUN_PARAGRAPH_APPLY:
370                 case LFUN_PARAGRAPH_UPDATE:
371                 case LFUN_NOACTION:
372                         status.enabled(false);
373                         return true;
374
375                 case LFUN_INSET_MODIFY:
376                 case LFUN_PASTE:
377                 case LFUN_PASTESELECTION:
378                         status.enabled(true);
379                         return true;
380
381                 // this one is difficult to get right. As a half-baked
382                 // solution, we consider only the first action of the sequence
383                 case LFUN_SEQUENCE: {
384                         // argument contains ';'-terminated commands
385                         string const firstcmd = token(cmd.argument, ';', 0);
386                         FuncRequest func(lyxaction.lookupFunc(firstcmd));
387                         func.origin = cmd.origin;
388                         return getStatus(cur, func, status);
389                 }
390
391                 default:
392                         return InsetCollapsable::getStatus(cur, cmd, status);
393         }
394 }
395
396
397 void InsetERT::setButtonLabel()
398 {
399         setLabel(isOpen() ?  _("ERT") : getNewLabel(_("ERT")));
400 }
401
402
403 bool InsetERT::insetAllowed(InsetBase::Code /* code */) const
404 {
405         return false;
406 }
407
408
409 void InsetERT::metrics(MetricsInfo & mi, Dimension & dim) const
410 {
411         LyXFont tmpfont = mi.base.font;
412         getDrawFont(mi.base.font);
413         mi.base.font.realize(tmpfont);
414         InsetCollapsable::metrics(mi, dim);
415         mi.base.font = tmpfont;
416         dim_ = dim;
417 }
418
419
420 void InsetERT::draw(PainterInfo & pi, int x, int y) const
421 {
422         LyXFont tmpfont = pi.base.font;
423         getDrawFont(pi.base.font);
424         pi.base.font.realize(tmpfont);
425         InsetCollapsable::draw(pi, x, y);
426         pi.base.font = tmpfont;
427 }
428
429
430 bool InsetERT::showInsetDialog(BufferView * bv) const
431 {
432         InsetERTMailer(const_cast<InsetERT &>(*this)).showDialog(bv);
433         return true;
434 }
435
436
437 void InsetERT::getDrawFont(LyXFont & font) const
438 {
439         font = LyXFont(LyXFont::ALL_INHERIT, latex_language);
440         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
441         font.setColor(LColor::latex);
442 }
443
444
445 string const InsetERTMailer::name_("ert");
446
447 InsetERTMailer::InsetERTMailer(InsetERT & inset)
448         : inset_(inset)
449 {}
450
451
452 string const InsetERTMailer::inset2string(Buffer const &) const
453 {
454         return params2string(inset_.status());
455 }
456
457
458 void InsetERTMailer::string2params(string const & in,
459                                    InsetCollapsable::CollapseStatus & status)
460 {
461         status = InsetCollapsable::Collapsed;
462         if (in.empty())
463                 return;
464
465         istringstream data(in);
466         LyXLex lex(0,0);
467         lex.setStream(data);
468
469         string name;
470         lex >> name;
471         if (name != name_)
472                 return print_mailer_error("InsetERTMailer", in, 1, name_);
473
474         int s;
475         lex >> s;
476         if (lex)
477                 status = static_cast<InsetCollapsable::CollapseStatus>(s);
478 }
479
480
481 string const
482 InsetERTMailer::params2string(InsetCollapsable::CollapseStatus status)
483 {
484         ostringstream data;
485         data << name_ << ' ' << status;
486         return data.str();
487 }