]> git.lyx.org Git - lyx.git/blob - src/insets/InsetBibitem.cpp
Further cleanup of collapsable insets. The layouts are now properly read and applied.
[lyx.git] / src / insets / InsetBibitem.cpp
1 /**
2  * \file InsetBibitem.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetBibitem.h"
14
15 #include "Buffer.h"
16 #include "BufferParams.h"
17 #include "BufferView.h"
18 #include "Counters.h"
19 #include "DispatchResult.h"
20 #include "FuncRequest.h"
21 #include "InsetIterator.h"
22 #include "InsetList.h"
23 #include "Lexer.h"
24 #include "Paragraph.h"
25 #include "ParagraphList.h"
26
27 #include "support/lstrings.h"
28 #include "support/std_ostream.h"
29 #include "support/docstream.h"
30 #include "support/convert.h"
31
32
33 namespace lyx {
34
35
36 int InsetBibitem::key_counter = 0;
37
38
39 docstring const key_prefix = from_ascii("key-");
40
41
42 InsetBibitem::InsetBibitem(InsetCommandParams const & p)
43         : InsetCommand(p, "bibitem")
44 {
45         if (getParam("key").empty())
46                 setParam("key", key_prefix + convert<docstring>(++key_counter));
47 }
48
49
50 CommandInfo const * InsetBibitem::findInfo(std::string const & /* cmdName */)
51 {
52         static const char * const paramnames[] = {"label", "key", ""};
53         static const bool isoptional[] = {true, false};
54         static const CommandInfo info = {2, paramnames, isoptional};
55         return &info;
56 }
57
58
59 Inset * InsetBibitem::clone() const
60 {
61         InsetBibitem * b = new InsetBibitem(params());
62         b->autolabel_ = autolabel_;
63         return b;
64 }
65
66
67 void InsetBibitem::doDispatch(Cursor & cur, FuncRequest & cmd)
68 {
69         switch (cmd.action) {
70
71         case LFUN_INSET_MODIFY: {
72                 InsetCommandParams p(BIBITEM_CODE);
73                 InsetCommandMailer::string2params("bibitem", to_utf8(cmd.argument()), p);
74                 if (p.getCmdName().empty()) {
75                         cur.noUpdate();
76                         break;
77                 }
78                 if (p["key"] != params()["key"])
79                         cur.bv().buffer().changeRefsIfUnique(params()["key"],
80                                                        p["key"], CITE_CODE);
81                 setParams(p);
82         }
83
84         default:
85                 InsetCommand::doDispatch(cur, cmd);
86                 break;
87         }
88 }
89
90
91 void InsetBibitem::read(Buffer const & buf, Lexer & lex)
92 {
93         InsetCommand::read(buf, lex);
94
95         if (support::prefixIs(getParam("key"), key_prefix)) {
96                 int const key = convert<int>(getParam("key").substr(key_prefix.length()));
97                 key_counter = std::max(key_counter, key);
98         }
99 }
100
101
102 docstring const InsetBibitem::getBibLabel() const
103 {
104         docstring const & label = getParam("label");
105         return label.empty() ? autolabel_ : label;
106 }
107
108
109 docstring const InsetBibitem::getScreenLabel(Buffer const &) const
110 {
111         return getParam("key") + " [" + getBibLabel() + ']';
112 }
113
114
115 int InsetBibitem::plaintext(Buffer const &, odocstream & os,
116                             OutputParams const &) const
117 {
118         odocstringstream oss;
119         oss << '[' << getBibLabel() << "] ";
120
121         docstring const str = oss.str();
122         os << str;
123
124         return str.size();
125 }
126
127
128 // ale070405
129 docstring const bibitemWidest(Buffer const & buffer)
130 {
131         int w = 0;
132
133         InsetBibitem const * bitem = 0;
134
135         // FIXME: this font is used unitialized for now but should  be set to
136         // a proportional font. Here is what Georg Baum has to say about it:
137         /*
138         bibitemWidest() is supposed to find the bibitem with the widest label in the
139         output, because that is needed as an argument of the bibliography
140         environment to dtermine the correct indentation. To be 100% correct we
141         would need the metrics of the font that is used in the output, but usually
142         we don't have access to these.
143         In practice, any proportional font is probably good enough, since we don't
144         need to know the final with, we only need to know the which label is the
145         widest.
146         Unless there is an easy way to get the metrics of the output font I suggest
147         to use a hardcoded font like "Times" or so.
148
149         It is very important that the result of this function is the same both with
150         and without GUI. After thinking about this it is clear that no Font
151         metrics should be used here, since these come from the gui. If we can't
152         easily get the LaTeX font metrics we should make our own poor mans font
153         metrics replacement, e.g. by hardcoding the metrics of the standard TeX
154         font.
155         */
156
157         ParagraphList::const_iterator it = buffer.paragraphs().begin();
158         ParagraphList::const_iterator end = buffer.paragraphs().end();
159
160         for (; it != end; ++it) {
161                 if (it->insetList().empty())
162                         continue;
163                 Inset * inset = it->insetList().begin()->inset;
164                 if (inset->lyxCode() != BIBITEM_CODE)
165                         continue;
166
167                 bitem = static_cast<InsetBibitem const *>(inset);
168                 docstring const label = bitem->getBibLabel();
169
170                 // FIXME: we can't be sure using the following that the GUI
171                 // version and the command-line version will give the same
172                 // result.
173                 //
174                 //int const wx = use_gui?
175                 //      theFontMetrics(font).width(label): label.size();
176                 //
177                 // So for now we just use the label size in order to be sure
178                 // that GUI and no-GUI gives the same bibitem (even if that is
179                 // potentially the wrong one.
180                 int const wx = label.size();
181
182                 if (wx > w)
183                         w = wx;
184         }
185
186         if (bitem && !bitem->getBibLabel().empty())
187                 return bitem->getBibLabel();
188
189         return from_ascii("99");
190 }
191
192
193 void InsetBibitem::fillWithBibKeys(Buffer const & buf,
194         BiblioInfo & keys, InsetIterator const & it) const
195 {
196         docstring const key = getParam("key");
197         BibTeXInfo keyvalmap;
198         keyvalmap[from_ascii("label")] = getParam("label");
199         DocIterator doc_it(it); 
200         doc_it.forwardPos();
201         keyvalmap[from_ascii("ref")] = doc_it.paragraph().asString(buf, false);
202         keyvalmap.isBibTeX = false;
203         keys[key] = keyvalmap;
204 }
205
206
207 /// Update the counters of this inset and of its contents
208 void InsetBibitem::updateLabels(Buffer const &buf, ParIterator const &) 
209 {
210         Counters & counters = buf.params().getTextClass().counters();
211         docstring const bibitem = from_ascii("bibitem");
212         if (counters.hasCounter(bibitem) && getParam("label").empty()) {
213                 counters.step(bibitem);
214                 autolabel_ = counters.theCounter(bibitem);
215         } else
216                 autolabel_ = from_ascii("??");
217         refresh();
218 }
219
220
221 } // namespace lyx