Richard Heck wrote: > > The attached patch updates the previous one in accord with JMarc's > comments. It's getting kind of large at this point. Sorry. But a lot of > it is just moving things around. > > There is one problem. In the old buffer::fillWithBibKeys() routine, we > tested against Inset::Codes and called an inset's fillWithBibKeys() > method in appropriate cases. JMarc suggested, sensibly enough, giving > Inset a virtual method that, by default, does nothing, and then just > calling fillWithBibKeys() for each inset. This is a nice idea, and it's > mostly implemented in this patch. But I simply can't get it to work for > InsetBibitem. Here's the code from the old routine: > for (InsetIterator it = inset_iterator_begin(buf->inset()); it; ++it) > { > if (it->lyxCode() == Inset::BIBITEM_CODE) { > InsetBibitem const & inset = > static_cast<InsetBibitem const &>(*it); > // FIXME UNICODE > string const key = to_utf8(inset.getParam("key")); > docstring const label = inset.getParam("label"); > DocIterator doc_it(it); > doc_it.forwardPos(); > docstring const ref = doc_it.paragraph().asString(*buf, > false); docstring const info = label + "TheBibliographyRef" + > ref; keys.push_back(pair<string, docstring>(key, info)); > } else .... > What we want instead is: > for (InsetIterator it = inset_iterator_begin(buf->inset()); it; ++it) > { > it->fillWithBibKeys(*buf, keys); > So we need an appropriate InsetBibitem::fillWithBibKeys(). So we cut and > paste: > void InsetBibitem::fillWithBibKeys(Buffer const & buf, > std::vector<std::pair<std::string, docstring> > & keys) const > { > string const key = to_utf8(getParam("key")); > docstring const label = getParam("label"); > The problem arises in the next line. Previously, we had a DocIterator to > work with. We don't have one now. But surely we can make one, right? > What seemed obvious to me was: > InsetBibitem & tmp = const_cast<InsetBibitem &>(*this); > DocIterator doc_it(tmp); > At which point we are back on track. > doc_it.forwardPos(); > docstring const ref = doc_it.paragraph().asString(buf, false); > //BOOOM! > docstring const info = label + biblio::TheBibliographyRef + ref; > keys.push_back(std::pair<string, docstring>(key, info)); > } > But this does not work. It segfaults where indicated, because there is > apparently no paragraph there. Worse, tracing the code suggests that > forwardPos() is having no effect. Obviously, my obvious idea about how > to create an appropriate DocIterator is wrong.
Have a look at http://wiki.lyx.org/Devel/Diagrams A properly formed DocIterator has root at the root inset of the Buffer. You can't build it knowing only one inset, as you have to know the full path arriving to it. (In fact, you can, but doing a full scan of the document which is normally not practical.) If you make a DocIterator based on some random inset, it serves only to iterate over all children of that inset. In other words, you need an iterator whose 'tip' is your inset, but you are building one whose 'root' is. So you have to pass it down, as JMarc suggests. A/