]> git.lyx.org Git - features.git/blob - src/insets/InsetNote.cpp
Allow removing words from the personal dictionary, that weren't previously added.
[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.find_effective()
211             && !runparams_in.find_with_non_output())
212                 return;
213
214         if (params_.type == InsetNoteParams::Note) {
215                 if (runparams_in.find_with_non_output()) {
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 (!runparams_in.find_with_non_output()) {
255                 if (params_.type == InsetNoteParams::Note)
256                         return 0;
257                 else if (params_.type == InsetNoteParams::Comment
258                     && runparams_in.find_effective())
259                         return 0;
260         }
261
262         OutputParams runparams(runparams_in);
263         if (params_.type != InsetNoteParams::Greyedout) {
264                 runparams.inComment = true;
265                 // Ignore files that are exported inside a comment
266                 runparams.exportdata.reset(new ExportData);
267         }
268         if (!runparams_in.find_with_non_output())
269                 os << '[' << buffer().B_("note") << ":\n";
270         InsetText::plaintext(os, runparams, max_length);
271         if (!runparams_in.find_with_non_output())
272                 os << "\n]";
273
274         return PLAINTEXT_NEWLINE + 1; // one char on a separate line
275 }
276
277
278 void InsetNote::docbook(XMLStream & xs, OutputParams const & runparams_in) const
279 {
280         if (params_.type == InsetNoteParams::Note)
281                 return;
282
283         OutputParams runparams(runparams_in);
284         if (params_.type == InsetNoteParams::Comment) {
285                 xs << xml::StartTag("remark");
286                 xs << xml::CR();
287                 runparams.inComment = true;
288                 // Ignore files that are exported inside a comment
289                 runparams.exportdata.reset(new ExportData);
290         }
291         // Greyed out text is output as such (no way to mark text as greyed out with DocBook).
292
293         InsetText::docbook(xs, runparams);
294
295         if (params_.type == InsetNoteParams::Comment) {
296                 xs << xml::CR();
297                 xs << xml::EndTag("remark");
298                 xs << xml::CR();
299         }
300 }
301
302
303 docstring InsetNote::xhtml(XMLStream & xs, OutputParams const & rp) const
304 {
305         if (params_.type == InsetNoteParams::Note)
306                 return docstring();
307
308         return InsetCollapsible::xhtml(xs, rp);
309 }
310
311
312 void InsetNote::validate(LaTeXFeatures & features) const
313 {
314         switch (params_.type) {
315         case InsetNoteParams::Comment:
316                 if (features.runparams().flavor == Flavor::Html)
317                         // we do output this but set display to "none" by default,
318                         // but people might want to use it.
319                         InsetCollapsible::validate(features);
320                 else
321                         // Only do the requires
322                         features.useInsetLayout(getLayout());
323                 break;
324         case InsetNoteParams::Greyedout:
325                 if (features.hasRTLLanguage())
326                         features.require("environ");
327                 InsetCollapsible::validate(features);
328                 break;
329         case InsetNoteParams::Note:
330                 break;
331         }
332 }
333
334
335 string InsetNote::contextMenuName() const
336 {
337         return "context-note";
338 }
339
340 bool InsetNote::allowSpellCheck() const
341 {
342         return (params_.type == InsetNoteParams::Greyedout || lyxrc.spellcheck_notes);
343 }
344
345 FontInfo InsetNote::getFont() const
346 {
347         FontInfo font = getLayout().font();
348         if (params_.type == InsetNoteParams::Greyedout
349             && buffer().params().isnotefontcolor) {
350                 ColorCode c = lcolor.getFromLyXName("notefontcolor");
351                 if (c != Color_none)
352                         font.setColor(c);
353                 // This is the local color (not overridden by other documents)
354                 ColorCode lc = lcolor.getFromLyXName("notefontcolor@" + buffer().fileName().absFileName());
355                 if (lc != Color_none)
356                         font.setPaintColor(lc);
357         }
358         return font;
359 }
360
361
362 string InsetNote::params2string(InsetNoteParams const & params)
363 {
364         ostringstream data;
365         data << "note" << ' ';
366         params.write(data);
367         return data.str();
368 }
369
370
371 void InsetNote::string2params(string const & in, InsetNoteParams & params)
372 {
373         params = InsetNoteParams();
374
375         if (in.empty())
376                 return;
377
378         istringstream data(in);
379         Lexer lex;
380         lex.setStream(data);
381         lex.setContext("InsetNote::string2params");
382         lex >> "note";
383         // There are cases, such as when we are called via getStatus() from
384         // Dialog::canApply(), where we are just called with "note" rather
385         // than a full "note Note TYPE".
386         if (!lex.isOK())
387                 return;
388         lex >> "Note";
389
390         params.read(lex);
391 }
392
393
394 } // namespace lyx