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