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