]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
The speed patch: redraw only rows that have changed
[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
62         setInsetName("ERT");
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<InsetBase> InsetERT::doClone() const
81 {
82         return auto_ptr<InsetBase>(new InsetERT(*this));
83 }
84
85
86 InsetERT::InsetERT(BufferParams const & bp,
87                    Language const *, string const & contents, CollapseStatus status)
88         : InsetCollapsable(bp, status)
89 {
90         //LyXFont font(LyXFont::ALL_INHERIT, lang);
91         LyXFont font;
92         getDrawFont(font);
93         string::const_iterator cit = contents.begin();
94         string::const_iterator end = contents.end();
95         pos_type pos = 0;
96         for (; cit != end; ++cit)
97                 paragraphs().begin()->insertChar(pos++, *cit, font);
98
99         // the init has to be after the initialization of the paragraph
100         // because of the label settings (draw_label for ert insets).
101         init();
102 }
103
104
105 InsetERT::~InsetERT()
106 {
107         InsetERTMailer(*this).hideDialog();
108 }
109
110
111 void InsetERT::write(Buffer const & buf, ostream & os) const
112 {
113         os << "ERT" << "\n";
114         InsetCollapsable::write(buf, os);
115 }
116
117
118 string const InsetERT::editMessage() const
119 {
120         return _("Opened ERT Inset");
121 }
122
123
124 int InsetERT::latex(Buffer const &, ostream & os,
125                     OutputParams const &) const
126 {
127         ParagraphList::const_iterator par = paragraphs().begin();
128         ParagraphList::const_iterator end = paragraphs().end();
129
130         int lines = 0;
131         while (par != end) {
132                 pos_type siz = par->size();
133                 for (pos_type i = 0; i < siz; ++i) {
134                         // ignore all struck out text
135                         if (isDeletedText(*par, i))
136                                 continue;
137
138                         os << par->getChar(i);
139                 }
140                 ++par;
141                 if (par != end) {
142                         os << "\n";
143                         ++lines;
144                 }
145         }
146
147         return lines;
148 }
149
150
151 int InsetERT::plaintext(Buffer const &, ostream &,
152                     OutputParams const & /*runparams*/) const
153 {
154         return 0;
155 }
156
157
158 int InsetERT::linuxdoc(Buffer const &, ostream & os,
159                        OutputParams const &) const
160 {
161         ParagraphList::const_iterator par = paragraphs().begin();
162         ParagraphList::const_iterator end = paragraphs().end();
163
164         int lines = 0;
165         while (par != end) {
166                 pos_type siz = par->size();
167                 for (pos_type i = 0; i < siz; ++i)
168                         os << par->getChar(i);
169                 ++par;
170                 if (par != end) {
171                         os << "\n";
172                         lines ++;
173                 }
174         }
175
176         return lines;
177 }
178
179
180 int InsetERT::docbook(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 void InsetERT::doDispatch(LCursor & cur, FuncRequest & cmd)
203 {
204         //lyxerr << "\nInsetERT::doDispatch (begin): cmd: " << cmd << endl;
205         switch (cmd.action) {
206
207         case LFUN_INSET_MODIFY: {
208                 InsetCollapsable::CollapseStatus st;
209                 InsetERTMailer::string2params(cmd.argument, st);
210                 setStatus(cur, st);
211                 break;
212         }
213         case LFUN_PASTE:
214         case LFUN_PASTESELECTION: {
215                 InsetCollapsable::doDispatch(cur, cmd);
216
217                 // Since we can only store plain text, we must reset all
218                 // attributes.
219                 // FIXME: Change only the pasted paragraphs
220
221                 BufferParams const & bp = cur.buffer().params();
222                 LyXLayout_ptr const layout =
223                         bp.getLyXTextClass().defaultLayout();
224                 LyXFont font = layout->font;
225                 // We need to set the language for non-english documents
226                 font.setLanguage(bp.language);
227                 ParagraphList::iterator const end = paragraphs().end();
228                 for (ParagraphList::iterator par = paragraphs().begin();
229                      par != end; ++par) {
230                         par->layout(layout);
231                         // in case par had a manual label
232                         par->setBeginOfBody();
233                         pos_type const siz = par->size();
234                         for (pos_type i = 0; i < siz; ++i) {
235                                 par->setFont(i, font);
236                         }
237                         par->params().clear();
238                 }
239                 break;
240         }
241         default:
242                 InsetCollapsable::doDispatch(cur, cmd);
243                 break;
244         }
245 }
246
247
248 bool InsetERT::getStatus(LCursor & cur, FuncRequest const & cmd,
249         FuncStatus & status) const
250 {
251         switch (cmd.action) {
252                 // suppress these
253                 case LFUN_ACUTE:
254                 case LFUN_BREVE:
255                 case LFUN_CARON:
256                 case LFUN_CEDILLA:
257                 case LFUN_CIRCLE:
258                 case LFUN_CIRCUMFLEX:
259                 case LFUN_DOT:
260                 case LFUN_GRAVE:
261                 case LFUN_HUNG_UMLAUT:
262                 case LFUN_MACRON:
263                 case LFUN_OGONEK:
264                 case LFUN_SPECIAL_CARON:
265                 case LFUN_TIE:
266                 case LFUN_TILDE:
267                 case LFUN_UMLAUT:
268                 case LFUN_UNDERBAR:
269                 case LFUN_UNDERDOT:
270                 case LFUN_APPENDIX:
271                 case LFUN_BREAKLINE:
272                 case LFUN_INSET_CAPTION:
273                 case LFUN_DEPTH_MIN:
274                 case LFUN_DEPTH_PLUS:
275                 case LFUN_LDOTS:
276                 case LFUN_END_OF_SENTENCE:
277                 case LFUN_ENVIRONMENT_INSERT:
278                 case LFUN_INSET_ERT:
279                 case LFUN_FILE_INSERT:
280                 case LFUN_INSET_FLOAT:
281                 case LFUN_INSET_WIDE_FLOAT:
282                 case LFUN_INSET_WRAP:
283                 case LFUN_BOLD:
284                 case LFUN_CODE:
285                 case LFUN_DEFAULT:
286                 case LFUN_EMPH:
287                 case LFUN_FREEFONT_APPLY:
288                 case LFUN_FREEFONT_UPDATE:
289                 case LFUN_NOUN:
290                 case LFUN_ROMAN:
291                 case LFUN_SANS:
292                 case LFUN_FRAK:
293                 case LFUN_ITAL:
294                 case LFUN_FONT_SIZE:
295                 case LFUN_FONT_STATE:
296                 case LFUN_UNDERLINE:
297                 case LFUN_INSET_FOOTNOTE:
298                 case LFUN_HFILL:
299                 case LFUN_HTMLURL:
300                 case LFUN_HYPHENATION:
301                 case LFUN_LIGATURE_BREAK:
302                 case LFUN_INDEX_INSERT:
303                 case LFUN_INDEX_PRINT:
304                 case LFUN_INSERT_LABEL:
305                 case LFUN_INSET_OPTARG:
306                 case LFUN_INSERT_BIBITEM:
307                 case LFUN_INSERT_LINE:
308                 case LFUN_INSERT_PAGEBREAK:
309                 case LFUN_LANGUAGE:
310                 case LFUN_LAYOUT:
311                 case LFUN_LAYOUT_PARAGRAPH:
312                 case LFUN_LAYOUT_TABULAR:
313                 case LFUN_INSET_MARGINAL:
314                 case LFUN_MATH_DISPLAY:
315                 case LFUN_INSERT_MATH:
316                 case LFUN_INSERT_MATRIX:
317                 case LFUN_MATH_MODE:
318                 case LFUN_MENU_OPEN_BY_NAME:
319                 case LFUN_MENU_SEPARATOR:
320                 case LFUN_INSERT_BRANCH:
321                 case LFUN_INSERT_CHARSTYLE:
322                 case LFUN_INSERT_NOTE:
323                 case LFUN_INSERT_BOX:
324                 case LFUN_GOTONOTE:
325                 case LFUN_PARAGRAPH_SPACING:
326                 case LFUN_QUOTE:
327                 case LFUN_LABEL_GOTO:
328                 case LFUN_REFERENCE_GOTO:
329                 case LFUN_SPACE_INSERT:
330                 case LFUN_GOTOFILEROW:
331                 case LFUN_NOTIFY:
332                 case LFUN_SETXY:
333                 case LFUN_TABULAR_INSERT:
334                 case LFUN_TOC_INSERT:
335                 case LFUN_URL:
336                 case LFUN_FLOAT_LIST:
337                 case LFUN_INSET_INSERT:
338                 case LFUN_PARAGRAPH_APPLY:
339                 case LFUN_PARAGRAPH_UPDATE:
340                 case LFUN_NOACTION:
341                         status.enabled(false);
342                         return true;
343
344                 case LFUN_INSET_MODIFY:
345                 case LFUN_PASTE:
346                 case LFUN_PASTESELECTION:
347                         status.enabled(true);
348                         return true;
349
350                 // this one is difficult to get right. As a half-baked
351                 // solution, we consider only the first action of the sequence
352                 case LFUN_SEQUENCE: {
353                         // argument contains ';'-terminated commands
354                         string const firstcmd = token(cmd.argument, ';', 0);
355                         FuncRequest func(lyxaction.lookupFunc(firstcmd));
356                         func.origin = cmd.origin;
357                         return getStatus(cur, func, status);
358                 }
359
360                 default:
361                         return InsetCollapsable::getStatus(cur, cmd, status);
362         }
363 }
364
365
366 void InsetERT::setButtonLabel()
367 {
368         setLabel(isOpen() ?  _("ERT") : getNewLabel(_("ERT")));
369 }
370
371
372 bool InsetERT::insetAllowed(InsetBase::Code /* code */) const
373 {
374         return false;
375 }
376
377
378 void InsetERT::metrics(MetricsInfo & mi, Dimension & dim) const
379 {
380         LyXFont tmpfont = mi.base.font;
381         getDrawFont(mi.base.font);
382         mi.base.font.realize(tmpfont);
383         InsetCollapsable::metrics(mi, dim);
384         mi.base.font = tmpfont;
385         dim_ = dim;
386 }
387
388
389 void InsetERT::draw(PainterInfo & pi, int x, int y) const
390 {
391         LyXFont tmpfont = pi.base.font;
392         getDrawFont(pi.base.font);
393         // I don't understand why the above .realize isn't needed, or
394         // even wanted, here. It just works. -- MV 10.04.2005
395         InsetCollapsable::draw(pi, x, y);
396         pi.base.font = tmpfont;
397 }
398
399
400 bool InsetERT::showInsetDialog(BufferView * bv) const
401 {
402         InsetERTMailer(const_cast<InsetERT &>(*this)).showDialog(bv);
403         return true;
404 }
405
406
407 void InsetERT::getDrawFont(LyXFont & font) const
408 {
409         font = LyXFont(LyXFont::ALL_INHERIT, latex_language);
410         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
411         font.setColor(LColor::latex);
412 }
413
414
415 string const InsetERTMailer::name_("ert");
416
417 InsetERTMailer::InsetERTMailer(InsetERT & inset)
418         : inset_(inset)
419 {}
420
421
422 string const InsetERTMailer::inset2string(Buffer const &) const
423 {
424         return params2string(inset_.status());
425 }
426
427
428 void InsetERTMailer::string2params(string const & in,
429                                    InsetCollapsable::CollapseStatus & status)
430 {
431         status = InsetCollapsable::Collapsed;
432         if (in.empty())
433                 return;
434
435         istringstream data(in);
436         LyXLex lex(0,0);
437         lex.setStream(data);
438
439         string name;
440         lex >> name;
441         if (name != name_)
442                 return print_mailer_error("InsetERTMailer", in, 1, name_);
443
444         int s;
445         lex >> s;
446         if (lex)
447                 status = static_cast<InsetCollapsable::CollapseStatus>(s);
448 }
449
450
451 string const
452 InsetERTMailer::params2string(InsetCollapsable::CollapseStatus status)
453 {
454         ostringstream data;
455         data << name_ << ' ' << status;
456         return data.str();
457 }