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