]> git.lyx.org Git - lyx.git/blob - src/insets/InsetERT.cpp
InsetListings: change the interface of diaplay function and allow AlignLeft. Applied...
[lyx.git] / src / insets / InsetERT.cpp
1 /**
2  * \file InsetERT.cpp
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 "Color.h"
27 #include "LyXAction.h"
28 #include "Lexer.h"
29 #include "TextClass.h"
30 #include "MetricsInfo.h"
31 #include "ParagraphParameters.h"
32 #include "Paragraph.h"
33
34 #include "frontends/alert.h"
35
36 #include <sstream>
37
38
39 namespace lyx {
40
41 using support::token;
42
43 using std::endl;
44 using std::min;
45
46 using std::auto_ptr;
47 using std::istringstream;
48 using std::ostream;
49 using std::ostringstream;
50 using std::string;
51
52
53 void InsetERT::init()
54 {
55         setButtonLabel();
56         Font font(Font::ALL_SANE);
57         font.decSize();
58         font.decSize();
59         font.setColor(Color::latex);
60         setLabelFont(font);
61         text_.current_font.setLanguage(latex_language);
62         text_.real_current_font.setLanguage(latex_language);
63 }
64
65
66 InsetERT::InsetERT(BufferParams const & bp, CollapseStatus status)
67         : InsetCollapsable(bp, status)
68 {
69         init();
70 }
71
72
73 InsetERT::InsetERT(InsetERT const & in)
74         : InsetCollapsable(in)
75 {
76         init();
77 }
78
79
80 auto_ptr<Inset> InsetERT::doClone() const
81 {
82         return auto_ptr<Inset>(new InsetERT(*this));
83 }
84
85
86 #if 0
87 InsetERT::InsetERT(BufferParams const & bp,
88                    Language const *, string const & contents, CollapseStatus status)
89         : InsetCollapsable(bp, status)
90 {
91         Font font(Font::ALL_INHERIT, latex_language);
92         paragraphs().begin()->insert(0, contents, font);
93
94         // the init has to be after the initialization of the paragraph
95         // because of the label settings (draw_label for ert insets).
96         init();
97 }
98 #endif
99
100
101 InsetERT::~InsetERT()
102 {
103         InsetERTMailer(*this).hideDialog();
104 }
105
106
107 void InsetERT::write(Buffer const & buf, ostream & os) const
108 {
109         os << "ERT" << "\n";
110         InsetCollapsable::write(buf, os);
111 }
112
113
114 void InsetERT::read(Buffer const & buf, Lexer & lex)
115 {
116         InsetCollapsable::read(buf, lex);
117
118         // Force default font
119         // This avoids paragraphs in buffer language that would have a
120         // foreign language after a document langauge change, and it ensures
121         // that all new text in ERT gets the "latex" language, since new text
122         // inherits the language from the last position of the existing text.
123         // As a side effect this makes us also robust against bugs in LyX
124         // that might lead to font changes in ERT in .lyx files.
125         Font font(Font::ALL_INHERIT, latex_language);
126         ParagraphList::iterator par = paragraphs().begin();
127         ParagraphList::iterator const end = paragraphs().end();
128         while (par != end) {
129                 pos_type siz = par->size();
130                 for (pos_type i = 0; i <= siz; ++i) {
131                         par->setFont(i, font);
132                 }
133                 ++par;
134         }
135 }
136
137
138 docstring const InsetERT::editMessage() const
139 {
140         return _("Opened ERT Inset");
141 }
142
143
144 int InsetERT::latex(Buffer const &, odocstream & os,
145                     OutputParams const &) const
146 {
147         ParagraphList::const_iterator par = paragraphs().begin();
148         ParagraphList::const_iterator end = paragraphs().end();
149
150         int lines = 0;
151         while (par != end) {
152                 pos_type siz = par->size();
153                 for (pos_type i = 0; i < siz; ++i) {
154                         // ignore all struck out text
155                         if (par->isDeleted(i))
156                                 continue;
157
158                         os.put(par->getChar(i));
159                 }
160                 ++par;
161                 if (par != end) {
162                         os << "\n";
163                         ++lines;
164                 }
165         }
166
167         return lines;
168 }
169
170
171 int InsetERT::plaintext(Buffer const &, odocstream &,
172                         OutputParams const &) const
173 {
174         return 0; // do not output TeX code
175 }
176
177
178 int InsetERT::docbook(Buffer const &, odocstream & os,
179                       OutputParams const &) const
180 {
181         ParagraphList::const_iterator par = paragraphs().begin();
182         ParagraphList::const_iterator end = paragraphs().end();
183
184         int lines = 0;
185         while (par != end) {
186                 pos_type siz = par->size();
187                 for (pos_type i = 0; i < siz; ++i)
188                         os.put(par->getChar(i));
189                 ++par;
190                 if (par != end) {
191                         os << "\n";
192                         ++lines;
193                 }
194         }
195
196         return lines;
197 }
198
199
200 void InsetERT::doDispatch(Cursor & cur, FuncRequest & cmd)
201 {
202         //lyxerr << "\nInsetERT::doDispatch (begin): cmd: " << cmd << endl;
203         switch (cmd.action) {
204
205         case LFUN_QUOTE_INSERT: {
206                 // We need to bypass the fancy quotes in Text
207                 FuncRequest f(LFUN_SELF_INSERT, "\"");
208                 dispatch(cur, f);
209                 break;
210         }
211         case LFUN_INSET_MODIFY: {
212                 InsetCollapsable::CollapseStatus st;
213                 InsetERTMailer::string2params(to_utf8(cmd.argument()), st);
214                 setStatus(cur, st);
215                 break;
216         }
217         case LFUN_PASTE:
218         case LFUN_CLIPBOARD_PASTE:
219         case LFUN_PRIMARY_SELECTION_PASTE: {
220                 InsetCollapsable::doDispatch(cur, cmd);
221
222                 // Since we can only store plain text, we must reset all
223                 // attributes.
224                 // FIXME: Change only the pasted paragraphs
225
226                 BufferParams const & bp = cur.buffer().params();
227                 Layout_ptr const layout =
228                         bp.getTextClass().defaultLayout();
229                 Font font = layout->font;
230                 // ERT contents has always latex_language
231                 font.setLanguage(latex_language);
232                 ParagraphList::iterator const end = paragraphs().end();
233                 for (ParagraphList::iterator par = paragraphs().begin();
234                      par != end; ++par) {
235                         // in case par had a manual label
236                         par->setBeginOfBody();
237                         pos_type const siz = par->size();
238                         for (pos_type i = 0; i < siz; ++i) {
239                                 par->setFont(i, font);
240                         }
241                         par->params().clear();
242                 }
243                 break;
244         }
245         default:
246                 // Force any new text to latex_language
247                 // FIXME: This should only be necessary in init(), but
248                 // new paragraphs that are created by pressing enter at the
249                 // start of an existing paragraph get the buffer language
250                 // and not latex_language, so we take this brute force
251                 // approach.
252                 text_.current_font.setLanguage(latex_language);
253                 text_.real_current_font.setLanguage(latex_language);
254
255                 InsetCollapsable::doDispatch(cur, cmd);
256                 break;
257         }
258 }
259
260
261 bool InsetERT::getStatus(Cursor & cur, FuncRequest const & cmd,
262         FuncStatus & status) const
263 {
264         switch (cmd.action) {
265                 // suppress these
266                 case LFUN_ACCENT_ACUTE:
267                 case LFUN_ACCENT_BREVE:
268                 case LFUN_ACCENT_CARON:
269                 case LFUN_ACCENT_CEDILLA:
270                 case LFUN_ACCENT_CIRCLE:
271                 case LFUN_ACCENT_CIRCUMFLEX:
272                 case LFUN_ACCENT_DOT:
273                 case LFUN_ACCENT_GRAVE:
274                 case LFUN_ACCENT_HUNGARIAN_UMLAUT:
275                 case LFUN_ACCENT_MACRON:
276                 case LFUN_ACCENT_OGONEK:
277                 case LFUN_ACCENT_SPECIAL_CARON:
278                 case LFUN_ACCENT_TIE:
279                 case LFUN_ACCENT_TILDE:
280                 case LFUN_ACCENT_UMLAUT:
281                 case LFUN_ACCENT_UNDERBAR:
282                 case LFUN_ACCENT_UNDERDOT:
283                 case LFUN_APPENDIX:
284                 case LFUN_BREAK_LINE:
285                 case LFUN_CAPTION_INSERT:
286                 case LFUN_DEPTH_DECREMENT:
287                 case LFUN_DEPTH_INCREMENT:
288                 case LFUN_DOTS_INSERT:
289                 case LFUN_END_OF_SENTENCE_PERIOD_INSERT:
290                 case LFUN_ENVIRONMENT_INSERT:
291                 case LFUN_ERT_INSERT:
292                 case LFUN_FILE_INSERT:
293                 case LFUN_FLOAT_INSERT:
294                 case LFUN_FLOAT_WIDE_INSERT:
295                 case LFUN_WRAP_INSERT:
296                 case LFUN_FONT_BOLD:
297                 case LFUN_FONT_CODE:
298                 case LFUN_FONT_DEFAULT:
299                 case LFUN_FONT_EMPH:
300                 case LFUN_FONT_FREE_APPLY:
301                 case LFUN_FONT_FREE_UPDATE:
302                 case LFUN_FONT_NOUN:
303                 case LFUN_FONT_ROMAN:
304                 case LFUN_FONT_SANS:
305                 case LFUN_FONT_FRAK:
306                 case LFUN_FONT_ITAL:
307                 case LFUN_FONT_SIZE:
308                 case LFUN_FONT_STATE:
309                 case LFUN_FONT_UNDERLINE:
310                 case LFUN_FOOTNOTE_INSERT:
311                 case LFUN_HFILL_INSERT:
312                 case LFUN_HTML_INSERT:
313                 case LFUN_HYPHENATION_POINT_INSERT:
314                 case LFUN_LIGATURE_BREAK_INSERT:
315                 case LFUN_INDEX_INSERT:
316                 case LFUN_INDEX_PRINT:
317                 case LFUN_LABEL_INSERT:
318                 case LFUN_OPTIONAL_INSERT:
319                 case LFUN_BIBITEM_INSERT:
320                 case LFUN_LINE_INSERT:
321                 case LFUN_PAGEBREAK_INSERT:
322                 case LFUN_CLEARPAGE_INSERT:
323                 case LFUN_CLEARDOUBLEPAGE_INSERT:
324                 case LFUN_LANGUAGE:
325                 case LFUN_LAYOUT:
326                 case LFUN_LAYOUT_PARAGRAPH:
327                 case LFUN_LAYOUT_TABULAR:
328                 case LFUN_MARGINALNOTE_INSERT:
329                 case LFUN_MATH_DISPLAY:
330                 case LFUN_MATH_INSERT:
331                 case LFUN_MATH_MATRIX:
332                 case LFUN_MATH_MODE:
333                 case LFUN_MENU_OPEN:
334                 case LFUN_MENU_SEPARATOR_INSERT:
335                 case LFUN_BRANCH_INSERT:
336                 case LFUN_CHARSTYLE_INSERT:
337                 case LFUN_NOTE_INSERT:
338                 case LFUN_BOX_INSERT:
339                 case LFUN_NOTE_NEXT:
340                 case LFUN_PARAGRAPH_SPACING:
341                 case LFUN_LABEL_GOTO:
342                 case LFUN_REFERENCE_NEXT:
343                 case LFUN_SPACE_INSERT:
344                 case LFUN_SERVER_GOTO_FILE_ROW:
345                 case LFUN_SERVER_NOTIFY:
346                 case LFUN_SERVER_SET_XY:
347                 case LFUN_TABULAR_INSERT:
348                 case LFUN_TOC_INSERT:
349                 case LFUN_URL_INSERT:
350                 case LFUN_FLOAT_LIST:
351                 case LFUN_INSET_INSERT:
352                 case LFUN_PARAGRAPH_PARAMS_APPLY:
353                 case LFUN_PARAGRAPH_UPDATE:
354                 case LFUN_NOMENCL_INSERT:
355                 case LFUN_NOMENCL_PRINT:
356                 case LFUN_NOACTION:
357                         status.enabled(false);
358                         return true;
359
360                 case LFUN_QUOTE_INSERT:
361                 case LFUN_INSET_MODIFY:
362                 case LFUN_PASTE:
363                 case LFUN_CLIPBOARD_PASTE:
364                 case LFUN_PRIMARY_SELECTION_PASTE:
365                         status.enabled(true);
366                         return true;
367
368                 // this one is difficult to get right. As a half-baked
369                 // solution, we consider only the first action of the sequence
370                 case LFUN_COMMAND_SEQUENCE: {
371                         // argument contains ';'-terminated commands
372                         string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
373                         FuncRequest func(lyxaction.lookupFunc(firstcmd));
374                         func.origin = cmd.origin;
375                         return getStatus(cur, func, status);
376                 }
377
378                 default:
379                         return InsetCollapsable::getStatus(cur, cmd, status);
380         }
381 }
382
383
384 void InsetERT::setButtonLabel()
385 {
386         // FIXME UNICODE
387         setLabel(isOpen() ?  _("ERT") : getNewLabel(_("ERT")));
388 }
389
390
391 bool InsetERT::insetAllowed(Inset::Code /* code */) const
392 {
393         return false;
394 }
395
396
397 bool InsetERT::metrics(MetricsInfo & mi, Dimension & dim) const
398 {
399         Font tmpfont = mi.base.font;
400         getDrawFont(mi.base.font);
401         mi.base.font.realize(tmpfont);
402         InsetCollapsable::metrics(mi, dim);
403         mi.base.font = tmpfont;
404         bool const changed = dim_ != dim;
405         dim_ = dim;
406         return changed;
407 }
408
409
410 void InsetERT::draw(PainterInfo & pi, int x, int y) const
411 {
412         Font tmpfont = pi.base.font;
413         getDrawFont(pi.base.font);
414         pi.base.font.realize(tmpfont);
415         InsetCollapsable::draw(pi, x, y);
416         pi.base.font = tmpfont;
417 }
418
419
420 bool InsetERT::showInsetDialog(BufferView * bv) const
421 {
422         InsetERTMailer(const_cast<InsetERT &>(*this)).showDialog(bv);
423         return true;
424 }
425
426
427 void InsetERT::getDrawFont(Font & font) const
428 {
429         font = Font(Font::ALL_INHERIT, latex_language);
430         font.setFamily(Font::TYPEWRITER_FAMILY);
431         font.setColor(Color::latex);
432 }
433
434
435 string const InsetERTMailer::name_("ert");
436
437 InsetERTMailer::InsetERTMailer(InsetERT & inset)
438         : inset_(inset)
439 {}
440
441
442 string const InsetERTMailer::inset2string(Buffer const &) const
443 {
444         return params2string(inset_.status());
445 }
446
447
448 void InsetERTMailer::string2params(string const & in,
449                                    InsetCollapsable::CollapseStatus & status)
450 {
451         status = InsetCollapsable::Collapsed;
452         if (in.empty())
453                 return;
454
455         istringstream data(in);
456         Lexer lex(0,0);
457         lex.setStream(data);
458
459         string name;
460         lex >> name;
461         if (name != name_)
462                 return print_mailer_error("InsetERTMailer", in, 1, name_);
463
464         int s;
465         lex >> s;
466         if (lex)
467                 status = static_cast<InsetCollapsable::CollapseStatus>(s);
468 }
469
470
471 string const
472 InsetERTMailer::params2string(InsetCollapsable::CollapseStatus status)
473 {
474         ostringstream data;
475         data << name_ << ' ' << status;
476         return data.str();
477 }
478
479
480 } // namespace lyx