]> git.lyx.org Git - lyx.git/blob - src/insets/InsetArgument.cpp
943adef319ef345a7024ee213314eea81712908c
[lyx.git] / src / insets / InsetArgument.cpp
1 /**
2  * \file InsetArgument.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Martin Vermeer
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetArgument.h"
15
16 #include "Cursor.h"
17 #include "FuncStatus.h"
18 #include "FuncRequest.h"
19 #include "InsetList.h"
20 #include "Layout.h"
21 #include "Lexer.h"
22 #include "ParIterator.h"
23
24 #include "support/convert.h"
25 #include "support/debug.h"
26 #include "support/docstream.h"
27 #include "support/gettext.h"
28 #include "support/lstrings.h"
29
30 using namespace std;
31
32 namespace lyx {
33
34
35 InsetArgument::InsetArgument(Buffer * buf, string const & name)
36     : InsetCollapsable(buf), name_(name), labelstring_(docstring())
37 {}
38
39
40 void InsetArgument::write(ostream & os) const
41 {
42         os << "Argument " << name_ << "\n";
43         InsetCollapsable::write(os);
44 }
45
46 void InsetArgument::read(Lexer & lex)
47 {
48         lex >> name_;
49         InsetCollapsable::read(lex);
50 }
51
52 void InsetArgument::updateBuffer(ParIterator const & it, UpdateType utype)
53 {
54         Layout::LaTeXArgMap args;
55         bool const insetlayout = &it.inset() && it.paragraph().layout().latexargs().empty();
56         if (insetlayout)
57                 args = it.inset().getLayout().latexargs();
58         else
59                 args = it.paragraph().layout().latexargs();
60
61         // Handle pre 2.1 ArgInsets (lyx2lyx cannot classify them)
62         if (name_ == "999") {
63                 unsigned int const req = insetlayout ? it.inset().getLayout().numRequiredArgs()
64                                       : it.paragraph().layout().requiredArgs();
65                 unsigned int const opts = insetlayout ? it.inset().getLayout().numOptArgs()
66                                       : it.paragraph().layout().optArgs();
67                 unsigned int nr = 0;
68                 unsigned int ours = 0;
69                 InsetList::const_iterator parit = it.paragraph().insetList().begin();
70                 InsetList::const_iterator parend = it.paragraph().insetList().end();
71                 for (; parit != parend; ++parit) {
72                         if (parit->inset->lyxCode() == ARG_CODE) {
73                                 ++nr;
74                                 if (parit->inset == this)
75                                         ours = nr;
76                         }
77                 }
78                 bool done = false;
79                 unsigned int realopts = 0;
80                 if (nr > req) {
81                         // We have optional arguments
82                         realopts = nr - req;
83                         if (ours <= realopts) {
84                                 name_ = convert<string>(ours);
85                                 done = true;
86                         }
87                 }
88                 if (!done) {
89                         // This is a mandatory argument. We have to consider
90                         // non-given optional arguments for the numbering
91                         int offset = opts - realopts;
92                         ours += offset;
93                         name_ = convert<string>(ours);
94                 }
95         }
96         Layout::LaTeXArgMap::const_iterator const lait =
97                         args.find(convert<unsigned int>(name_));
98         if (lait != args.end()) {
99                 docstring label = translateIfPossible((*lait).second.labelstring);
100                 docstring striplabel;
101                 support::rsplit(label, striplabel, '|');
102                 labelstring_ = striplabel.empty() ? label: striplabel;
103                 tooltip_ = translateIfPossible((*lait).second.tooltip);
104         } else {
105                 labelstring_ = _("Unknown Argument");
106                 tooltip_ = _("Argument not known in this Layout. Will be supressed in the output.");
107         }
108         setButtonLabel();
109         InsetCollapsable::updateBuffer(it, utype);
110 }
111
112 void InsetArgument::setButtonLabel()
113 {
114         setLabel(labelstring_);
115 }
116
117 docstring InsetArgument::toolTip(BufferView const & bv, int, int) const
118 {
119         if (isOpen(bv))
120                 return tooltip_;
121         return toolTipText(tooltip_ + from_ascii(":\n"));
122 }
123
124 void InsetArgument::doDispatch(Cursor & cur, FuncRequest & cmd)
125 {
126         switch (cmd.action()) {
127
128         case LFUN_INSET_MODIFY: {
129                 string const first_arg = cmd.getArg(0);
130                 bool const change_type = first_arg == "changetype";
131                 if (!change_type) {
132                         // not for us
133                         // this will not be handled higher up
134                         cur.undispatched();
135                         return;
136                 }
137                 cur.recordUndoInset(ATOMIC_UNDO, this);
138                 name_ = cmd.getArg(1);
139                 cur.forceBufferUpdate();
140                 break;
141         }
142
143         default:
144                 InsetCollapsable::doDispatch(cur, cmd);
145                 break;
146         }
147 }
148
149
150 bool InsetArgument::getStatus(Cursor & cur, FuncRequest const & cmd,
151                 FuncStatus & flag) const
152 {
153         switch (cmd.action()) {
154
155         case LFUN_INSET_MODIFY: {
156                 string const first_arg = cmd.getArg(0);
157                 if (first_arg == "changetype") {
158                         string const type = cmd.getArg(1);
159                         flag.setOnOff(type == name_);
160                         if (type == name_) {
161                                 flag.setEnabled(true);
162                                 return true;
163                         }
164                         Layout::LaTeXArgMap args;
165                         bool const insetlayout = &cur.inset() && cur.paragraph().layout().latexargs().empty();
166                         if (insetlayout)
167                                 args = cur.inset().getLayout().latexargs();
168                         else
169                                 args = cur.paragraph().layout().latexargs();
170                         Layout::LaTeXArgMap::const_iterator const lait =
171                                         args.find(convert<unsigned int>(type));
172                         if (lait != args.end()) {
173                                 flag.setEnabled(true);
174                                 InsetList::const_iterator it = cur.paragraph().insetList().begin();
175                                 InsetList::const_iterator end = cur.paragraph().insetList().end();
176                                 for (; it != end; ++it) {
177                                         if (it->inset->lyxCode() == ARG_CODE) {
178                                                 InsetArgument const * ins =
179                                                         static_cast<InsetArgument const *>(it->inset);
180                                                 if (ins->name() == type) {
181                                                         // we have this already
182                                                         flag.setEnabled(false);
183                                                         return true;
184                                                 }
185                                         }
186                                 }
187                         } else
188                                 flag.setEnabled(false);
189                         return true;
190                 }
191                 return InsetCollapsable::getStatus(cur, cmd, flag);
192         }
193
194         default:
195                 return InsetCollapsable::getStatus(cur, cmd, flag);
196         }
197 }
198
199 string InsetArgument::contextMenuName() const
200 {
201         return "context-argument";
202 }
203
204 void InsetArgument::latexArgument(otexstream & os,
205                 OutputParams const & runparams, docstring const & ldelim,
206                 docstring const & rdelim) const
207 {
208         TexRow texrow;
209         odocstringstream ss;
210         otexstream ots(ss, texrow);
211         InsetText::latex(ots, runparams);
212         docstring str = ss.str();
213         if (ldelim != "{" && support::contains(str, rdelim))
214                 str = '{' + str + '}';
215         os << ldelim << str << rdelim;
216 }
217
218
219 } // namespace lyx