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