]> git.lyx.org Git - lyx.git/blob - src/insets/InsetBibitem.cpp
simplification
[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 #include "TextClass.h"
27
28 #include "support/lstrings.h"
29 #include "support/docstream.h"
30 #include "support/convert.h"
31
32 #include <ostream>
33
34 namespace lyx {
35
36
37 int InsetBibitem::key_counter = 0;
38
39
40 docstring const key_prefix = from_ascii("key-");
41
42
43 InsetBibitem::InsetBibitem(InsetCommandParams const & p)
44         : InsetCommand(p, "bibitem")
45 {
46         if (getParam("key").empty())
47                 setParam("key", key_prefix + convert<docstring>(++key_counter));
48 }
49
50
51 CommandInfo const * InsetBibitem::findInfo(std::string const & /* cmdName */)
52 {
53         static const char * const paramnames[] = {"label", "key", ""};
54         static const bool isoptional[] = {true, false};
55         static const CommandInfo info = {2, paramnames, isoptional};
56         return &info;
57 }
58
59
60 Inset * InsetBibitem::clone() const
61 {
62         InsetBibitem * b = new InsetBibitem(params());
63         b->autolabel_ = autolabel_;
64         return b;
65 }
66
67
68 void InsetBibitem::doDispatch(Cursor & cur, FuncRequest & cmd)
69 {
70         switch (cmd.action) {
71
72         case LFUN_INSET_MODIFY: {
73                 InsetCommandParams p(BIBITEM_CODE);
74                 InsetCommandMailer::string2params("bibitem", to_utf8(cmd.argument()), p);
75                 if (p.getCmdName().empty()) {
76                         cur.noUpdate();
77                         break;
78                 }
79                 if (p["key"] != params()["key"])
80                         cur.bv().buffer().changeRefsIfUnique(params()["key"],
81                                                        p["key"], CITE_CODE);
82                 setParams(p);
83         }
84
85         default:
86                 InsetCommand::doDispatch(cur, cmd);
87                 break;
88         }
89 }
90
91
92 void InsetBibitem::read(Buffer const & buf, Lexer & lex)
93 {
94         InsetCommand::read(buf, lex);
95
96         if (support::prefixIs(getParam("key"), key_prefix)) {
97                 int const key = convert<int>(getParam("key").substr(key_prefix.length()));
98                 key_counter = std::max(key_counter, key);
99         }
100 }
101
102
103 docstring const InsetBibitem::getBibLabel() const
104 {
105         docstring const & label = getParam("label");
106         return label.empty() ? autolabel_ : label;
107 }
108
109
110 docstring const InsetBibitem::getScreenLabel(Buffer const &) const
111 {
112         return getParam("key") + " [" + getBibLabel() + ']';
113 }
114
115
116 int InsetBibitem::plaintext(Buffer const &, odocstream & os,
117                             OutputParams const &) const
118 {
119         odocstringstream oss;
120         oss << '[' << getBibLabel() << "] ";
121
122         docstring const str = oss.str();
123         os << str;
124
125         return str.size();
126 }
127
128
129 // ale070405
130 docstring const bibitemWidest(Buffer const & buffer)
131 {
132         int w = 0;
133
134         InsetBibitem const * bitem = 0;
135
136         // FIXME: this font is used unitialized for now but should  be set to
137         // a proportional font. Here is what Georg Baum has to say about it:
138         /*
139         bibitemWidest() is supposed to find the bibitem with the widest label in the
140         output, because that is needed as an argument of the bibliography
141         environment to dtermine the correct indentation. To be 100% correct we
142         would need the metrics of the font that is used in the output, but usually
143         we don't have access to these.
144         In practice, any proportional font is probably good enough, since we don't
145         need to know the final with, we only need to know the which label is the
146         widest.
147         Unless there is an easy way to get the metrics of the output font I suggest
148         to use a hardcoded font like "Times" or so.
149
150         It is very important that the result of this function is the same both with
151         and without GUI. After thinking about this it is clear that no Font
152         metrics should be used here, since these come from the gui. If we can't
153         easily get the LaTeX font metrics we should make our own poor mans font
154         metrics replacement, e.g. by hardcoding the metrics of the standard TeX
155         font.
156         */
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