]> git.lyx.org Git - lyx.git/blob - src/insets/InsetBibitem.cpp
InsetIndex is no longer an InsetCommand.
[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 "Font.h"
22 #include "InsetIterator.h"
23 #include "InsetList.h"
24 #include "Lexer.h"
25 #include "Paragraph.h"
26 #include "ParagraphList.h"
27
28 #include "support/lstrings.h"
29 #include "support/std_ostream.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 front
153         metrics replacement, e.g. by hardcoding the metrics of the standard TeX
154         font.
155         */
156         Font font;
157
158         ParagraphList::const_iterator it = buffer.paragraphs().begin();
159         ParagraphList::const_iterator end = buffer.paragraphs().end();
160
161         for (; it != end; ++it) {
162                 if (it->insetList().empty())
163                         continue;
164                 Inset * inset = it->insetList().begin()->inset;
165                 if (inset->lyxCode() != BIBITEM_CODE)
166                         continue;
167
168                 bitem = static_cast<InsetBibitem const *>(inset);
169                 docstring const label = bitem->getBibLabel();
170
171                 // FIXME: we can't be sure using the following that the GUI
172                 // version and the command-line version will give the same
173                 // result.
174                 //
175                 //int const wx = use_gui?
176                 //      theFontMetrics(font).width(label): label.size();
177                 //
178                 // So for now we just use the label size in order to be sure
179                 // that GUI and no-GUI gives the same bibitem (even if that is
180                 // potentially the wrong one.
181                 int const wx = label.size();
182
183                 if (wx > w)
184                         w = wx;
185         }
186
187         if (bitem && !bitem->getBibLabel().empty())
188                 return bitem->getBibLabel();
189
190         return from_ascii("99");
191 }
192
193
194 void InsetBibitem::fillWithBibKeys(Buffer const & buf,
195         BiblioInfo & keys, InsetIterator const & it) const
196 {
197         docstring const key = getParam("key");
198         BibTeXInfo keyvalmap;
199         keyvalmap[from_ascii("label")] = getParam("label");
200         DocIterator doc_it(it); 
201         doc_it.forwardPos();
202         keyvalmap[from_ascii("ref")] = doc_it.paragraph().asString(buf, false);
203         keyvalmap.isBibTeX = false;
204         keys[key] = keyvalmap;
205 }
206
207
208 /// Update the counters of this inset and of its contents
209 void InsetBibitem::updateLabels(Buffer const &buf, ParIterator const &) 
210 {
211         Counters & counters = buf.params().getTextClass().counters();
212         docstring const bibitem = from_ascii("bibitem");
213         if (counters.hasCounter(bibitem) && getParam("label").empty()) {
214                 counters.step(bibitem);
215                 autolabel_ = counters.theCounter(bibitem);
216         } else
217                 autolabel_ = from_ascii("??");
218         refresh();
219 }
220
221
222 } // namespace lyx