]> git.lyx.org Git - features.git/blob - src/insets/InsetNote.cpp
More enums & includes refactoring
[features.git] / src / insets / InsetNote.cpp
1 /**
2  * \file InsetNote.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  * \author Martin Vermeer
8  * \author Jürgen Spitzmüller
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "InsetNote.h"
16
17 #include "Buffer.h"
18 #include "BufferParams.h"
19 #include "BufferView.h"
20 #include "ColorSet.h"
21 #include "Cursor.h"
22 #include "Exporter.h"
23 #include "FontInfo.h"
24 #include "FuncRequest.h"
25 #include "FuncStatus.h"
26 #include "InsetLayout.h"
27 #include "LaTeXFeatures.h"
28 #include "Lexer.h"
29 #include "LyXRC.h"
30 #include "output_docbook.h"
31
32 #include "support/debug.h"
33 #include "support/docstream.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
36 #include "support/Translator.h"
37
38 #include "frontends/Application.h"
39
40 #include <algorithm>
41 #include <sstream>
42
43 using namespace std;
44
45 namespace lyx {
46
47 namespace {
48
49 typedef Translator<string, InsetNoteParams::Type> NoteTranslator;
50
51 NoteTranslator const init_notetranslator()
52 {
53         NoteTranslator translator("Note", InsetNoteParams::Note);
54         translator.addPair("Comment", InsetNoteParams::Comment);
55         translator.addPair("Greyedout", InsetNoteParams::Greyedout);
56         return translator;
57 }
58
59
60 NoteTranslator const & notetranslator()
61 {
62         static NoteTranslator const translator = init_notetranslator();
63         return translator;
64 }
65
66
67 } // namespace
68
69
70 InsetNoteParams::InsetNoteParams()
71         : type(Note)
72 {}
73
74
75 void InsetNoteParams::write(ostream & os) const
76 {
77         string const label = notetranslator().find(type);
78         os << "Note " << label << "\n";
79 }
80
81
82 void InsetNoteParams::read(Lexer & lex)
83 {
84         string label;
85         lex >> label;
86         if (lex)
87                 type = notetranslator().find(label);
88 }
89
90
91 /////////////////////////////////////////////////////////////////////
92 //
93 // InsetNote
94 //
95 /////////////////////////////////////////////////////////////////////
96
97 InsetNote::InsetNote(Buffer * buf, string const & label)
98         : InsetCollapsible(buf)
99 {
100         params_.type = notetranslator().find(label);
101 }
102
103
104 InsetNote::~InsetNote()
105 {
106         hideDialogs("note", this);
107 }
108
109
110 docstring InsetNote::layoutName() const
111 {
112         return from_ascii("Note:" + notetranslator().find(params_.type));
113 }
114
115
116 void InsetNote::write(ostream & os) const
117 {
118         params_.write(os);
119         InsetCollapsible::write(os);
120 }
121
122
123 void InsetNote::read(Lexer & lex)
124 {
125         params_.read(lex);
126         InsetCollapsible::read(lex);
127 }
128
129
130 bool InsetNote::showInsetDialog(BufferView * bv) const
131 {
132         bv->showDialog("note", params2string(params()),
133                 const_cast<InsetNote *>(this));
134         return true;
135 }
136
137
138 void InsetNote::doDispatch(Cursor & cur, FuncRequest & cmd)
139 {
140         switch (cmd.action()) {
141
142         case LFUN_INSET_MODIFY: {
143                 // Do not do anything if converting to the same type of Note.
144                 // A quick break here is done instead of disabling the LFUN
145                 // because disabling the LFUN would lead to a greyed out
146                 // entry, which might confuse users.
147                 // In the future, we might want to have a radio button for
148                 // switching between notes.
149                 InsetNoteParams params;
150                 string2params(to_utf8(cmd.argument()), params);
151                 if (params_.type == params.type)
152                   break;
153
154                 cur.recordUndoInset(this);
155                 string2params(to_utf8(cmd.argument()), params_);
156                 setButtonLabel();
157                 // what we really want here is a TOC update, but that means
158                 // a full buffer update
159                 cur.forceBufferUpdate();
160                 break;
161         }
162
163         case LFUN_INSET_DIALOG_UPDATE:
164                 cur.bv().updateDialog("note", params2string(params()));
165                 break;
166
167         default:
168                 InsetCollapsible::doDispatch(cur, cmd);
169                 break;
170         }
171 }
172
173
174 bool InsetNote::getStatus(Cursor & cur, FuncRequest const & cmd,
175                 FuncStatus & flag) const
176 {
177         switch (cmd.action()) {
178
179         case LFUN_INSET_MODIFY:
180                 if (cmd.getArg(0) == "note") {
181                         InsetNoteParams params;
182                         string2params(to_utf8(cmd.argument()), params);
183                         flag.setOnOff(params_.type == params.type);
184                 }
185                 return true;
186
187         case LFUN_INSET_DIALOG_UPDATE:
188                 flag.setEnabled(true);
189                 return true;
190
191         default:
192                 return InsetCollapsible::getStatus(cur, cmd, flag);
193         }
194 }
195
196
197 bool InsetNote::isMacroScope() const
198 {
199         // LyX note has no latex output
200         if (params_.type == InsetNoteParams::Note)
201                 return true;
202
203         return InsetCollapsible::isMacroScope();
204 }
205
206
207 void InsetNote::latex(otexstream & os, OutputParams const & runparams_in) const
208 {
209         if (params_.type == InsetNoteParams::Note)
210                 return;
211
212         OutputParams runparams(runparams_in);
213         if (params_.type == InsetNoteParams::Comment) {
214                 runparams.inComment = true;
215                 // Ignore files that are exported inside a comment
216                 runparams.exportdata.reset(new ExportData);
217         }
218
219         // the space after the comment in 'a[comment] b' will be eaten by the
220         // comment environment since the space before b is ignored with the
221         // following latex output:
222         //
223         // a%
224         // \begin{comment}
225         // comment
226         // \end{comment}
227         //  b
228         //
229         // Adding {} before ' b' fixes this.
230         // The {} will be automatically added, but only if needed, for all
231         // insets whose InsetLayout Display tag is false. This is achieved
232         // by telling otexstream to protect an immediately following space
233         // and is done for both comment and greyedout insets.
234         InsetCollapsible::latex(os, runparams);
235
236         runparams_in.encoding = runparams.encoding;
237 }
238
239
240 int InsetNote::plaintext(odocstringstream & os,
241                          OutputParams const & runparams_in, size_t max_length) const
242 {
243         if (params_.type == InsetNoteParams::Note)
244                 return 0;
245
246         OutputParams runparams(runparams_in);
247         if (params_.type == InsetNoteParams::Comment) {
248                 runparams.inComment = true;
249                 // Ignore files that are exported inside a comment
250                 runparams.exportdata.reset(new ExportData);
251         }
252         os << '[' << buffer().B_("note") << ":\n";
253         InsetText::plaintext(os, runparams, max_length);
254         os << "\n]";
255
256         return PLAINTEXT_NEWLINE + 1; // one char on a separate line
257 }
258
259
260 void InsetNote::docbook(XMLStream & xs, OutputParams const & runparams_in) const
261 {
262         if (params_.type == InsetNoteParams::Note)
263                 return;
264
265         OutputParams runparams(runparams_in);
266         if (params_.type == InsetNoteParams::Comment) {
267                 xs << xml::StartTag("remark");
268                 xs << xml::CR();
269                 runparams.inComment = true;
270                 // Ignore files that are exported inside a comment
271                 runparams.exportdata.reset(new ExportData);
272         }
273         // Greyed out text is output as such (no way to mark text as greyed out with DocBook).
274
275         InsetText::docbook(xs, runparams);
276
277         if (params_.type == InsetNoteParams::Comment) {
278                 xs << xml::CR();
279                 xs << xml::EndTag("remark");
280                 xs << xml::CR();
281         }
282 }
283
284
285 docstring InsetNote::xhtml(XMLStream & xs, OutputParams const & rp) const
286 {
287         if (params_.type == InsetNoteParams::Note)
288                 return docstring();
289
290         return InsetCollapsible::xhtml(xs, rp);
291 }
292
293
294 void InsetNote::validate(LaTeXFeatures & features) const
295 {
296         switch (params_.type) {
297         case InsetNoteParams::Comment:
298                 if (features.runparams().flavor == Flavor::Html)
299                         // we do output this but set display to "none" by default,
300                         // but people might want to use it.
301                         InsetCollapsible::validate(features);
302                 else
303                         // Only do the requires
304                         features.useInsetLayout(getLayout());
305                 break;
306         case InsetNoteParams::Greyedout:
307                 if (features.hasRTLLanguage())
308                         features.require("environ");
309                 InsetCollapsible::validate(features);
310                 break;
311         case InsetNoteParams::Note:
312                 break;
313         }
314 }
315
316
317 string InsetNote::contextMenuName() const
318 {
319         return "context-note";
320 }
321
322 bool InsetNote::allowSpellCheck() const
323 {
324         return (params_.type == InsetNoteParams::Greyedout || lyxrc.spellcheck_notes);
325 }
326
327 FontInfo InsetNote::getFont() const
328 {
329         FontInfo font = getLayout().font();
330         // FIXME: This hardcoded color is a hack!
331         if (params_.type == InsetNoteParams::Greyedout
332             && buffer().params().notefontcolor != lyx::rgbFromHexName("#cccccc")) {
333                 ColorCode c = lcolor.getFromLyXName("notefontcolor");
334                 if (c != Color_none)
335                         font.setColor(c);
336         }
337         return font;
338 }
339
340
341 string InsetNote::params2string(InsetNoteParams const & params)
342 {
343         ostringstream data;
344         data << "note" << ' ';
345         params.write(data);
346         return data.str();
347 }
348
349
350 void InsetNote::string2params(string const & in, InsetNoteParams & params)
351 {
352         params = InsetNoteParams();
353
354         if (in.empty())
355                 return;
356
357         istringstream data(in);
358         Lexer lex;
359         lex.setStream(data);
360         lex.setContext("InsetNote::string2params");
361         lex >> "note";
362         // There are cases, such as when we are called via getStatus() from
363         // Dialog::canApply(), where we are just called with "note" rather
364         // than a full "note Note TYPE".
365         if (!lex.isOK())
366                 return;
367         lex >> "Note";
368
369         params.read(lex);
370 }
371
372
373 } // namespace lyx