]> git.lyx.org Git - features.git/blob - src/insets/InsetNote.cpp
Amend d96135a9dcc5
[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::Greyedout
210             && runparams_in.for_searchAdv != OutputParams::NoSearch
211             && (runparams_in.for_searchAdv & OutputParams::SearchNonOutput) == 0)
212                 return;
213
214         if (params_.type == InsetNoteParams::Note) {
215                 if ((runparams_in.for_searchAdv & OutputParams::SearchNonOutput) != 0) {
216                         OutputParams runparams(runparams_in);
217                         InsetCollapsible::latex(os, runparams);
218                         runparams_in.encoding = runparams.encoding;
219                 }
220                 return;
221         }
222
223         OutputParams runparams(runparams_in);
224         if (params_.type == InsetNoteParams::Comment) {
225                 runparams.inComment = true;
226                 // Ignore files that are exported inside a comment
227                 runparams.exportdata.reset(new ExportData);
228         }
229
230         // the space after the comment in 'a[comment] b' will be eaten by the
231         // comment environment since the space before b is ignored with the
232         // following latex output:
233         //
234         // a%
235         // \begin{comment}
236         // comment
237         // \end{comment}
238         //  b
239         //
240         // Adding {} before ' b' fixes this.
241         // The {} will be automatically added, but only if needed, for all
242         // insets whose InsetLayout Display tag is false. This is achieved
243         // by telling otexstream to protect an immediately following space
244         // and is done for both comment and greyedout insets.
245         InsetCollapsible::latex(os, runparams);
246
247         runparams_in.encoding = runparams.encoding;
248 }
249
250
251 int InsetNote::plaintext(odocstringstream & os,
252                          OutputParams const & runparams_in, size_t max_length) const
253 {
254         if (params_.type == InsetNoteParams::Note)
255                 return 0;
256
257         OutputParams runparams(runparams_in);
258         if (params_.type == InsetNoteParams::Comment) {
259                 runparams.inComment = true;
260                 // Ignore files that are exported inside a comment
261                 runparams.exportdata.reset(new ExportData);
262         }
263         os << '[' << buffer().B_("note") << ":\n";
264         InsetText::plaintext(os, runparams, max_length);
265         os << "\n]";
266
267         return PLAINTEXT_NEWLINE + 1; // one char on a separate line
268 }
269
270
271 void InsetNote::docbook(XMLStream & xs, OutputParams const & runparams_in) const
272 {
273         if (params_.type == InsetNoteParams::Note)
274                 return;
275
276         OutputParams runparams(runparams_in);
277         if (params_.type == InsetNoteParams::Comment) {
278                 xs << xml::StartTag("remark");
279                 xs << xml::CR();
280                 runparams.inComment = true;
281                 // Ignore files that are exported inside a comment
282                 runparams.exportdata.reset(new ExportData);
283         }
284         // Greyed out text is output as such (no way to mark text as greyed out with DocBook).
285
286         InsetText::docbook(xs, runparams);
287
288         if (params_.type == InsetNoteParams::Comment) {
289                 xs << xml::CR();
290                 xs << xml::EndTag("remark");
291                 xs << xml::CR();
292         }
293 }
294
295
296 docstring InsetNote::xhtml(XMLStream & xs, OutputParams const & rp) const
297 {
298         if (params_.type == InsetNoteParams::Note)
299                 return docstring();
300
301         return InsetCollapsible::xhtml(xs, rp);
302 }
303
304
305 void InsetNote::validate(LaTeXFeatures & features) const
306 {
307         switch (params_.type) {
308         case InsetNoteParams::Comment:
309                 if (features.runparams().flavor == Flavor::Html)
310                         // we do output this but set display to "none" by default,
311                         // but people might want to use it.
312                         InsetCollapsible::validate(features);
313                 else
314                         // Only do the requires
315                         features.useInsetLayout(getLayout());
316                 break;
317         case InsetNoteParams::Greyedout:
318                 if (features.hasRTLLanguage())
319                         features.require("environ");
320                 InsetCollapsible::validate(features);
321                 break;
322         case InsetNoteParams::Note:
323                 break;
324         }
325 }
326
327
328 string InsetNote::contextMenuName() const
329 {
330         return "context-note";
331 }
332
333 bool InsetNote::allowSpellCheck() const
334 {
335         return (params_.type == InsetNoteParams::Greyedout || lyxrc.spellcheck_notes);
336 }
337
338 FontInfo InsetNote::getFont() const
339 {
340         FontInfo font = getLayout().font();
341         if (params_.type == InsetNoteParams::Greyedout
342             && buffer().params().isnotefontcolor) {
343                 ColorCode c = lcolor.getFromLyXName("notefontcolor");
344                 if (c != Color_none)
345                         font.setColor(c);
346                 // This is the local color (not overridden by other documents)
347                 ColorCode lc = lcolor.getFromLyXName("notefontcolor@" + buffer().fileName().absFileName());
348                 if (lc != Color_none)
349                         font.setPaintColor(lc);
350         }
351         return font;
352 }
353
354
355 string InsetNote::params2string(InsetNoteParams const & params)
356 {
357         ostringstream data;
358         data << "note" << ' ';
359         params.write(data);
360         return data.str();
361 }
362
363
364 void InsetNote::string2params(string const & in, InsetNoteParams & params)
365 {
366         params = InsetNoteParams();
367
368         if (in.empty())
369                 return;
370
371         istringstream data(in);
372         Lexer lex;
373         lex.setStream(data);
374         lex.setContext("InsetNote::string2params");
375         lex >> "note";
376         // There are cases, such as when we are called via getStatus() from
377         // Dialog::canApply(), where we are just called with "note" rather
378         // than a full "note Note TYPE".
379         if (!lex.isOK())
380                 return;
381         lex >> "Note";
382
383         params.read(lex);
384 }
385
386
387 } // namespace lyx