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