3 * This file is part of LyX, the document processor.
\r
4 * Licence details can be found in the file COPYING.
\r
6 * \author Jean-Marc Lasgouttes
\r
7 * \author Angus Leeming
\r
8 * \author Abdelrazak Younes
\r
10 * Full author contact details are available in file CREDITS.
\r
18 #include "bufferparams.h"
\r
19 #include "FloatList.h"
\r
20 #include "funcrequest.h"
\r
21 #include "LyXAction.h"
\r
22 #include "paragraph.h"
\r
26 #include "frontends/LyXView.h"
\r
28 #include "insets/insetfloat.h"
\r
29 #include "insets/insetoptarg.h"
\r
30 #include "insets/insetwrap.h"
\r
32 #include "support/convert.h"
\r
45 static TocBackend::Toc empty_toc_;
\r
47 ///////////////////////////////////////////////////////////////////////////
\r
48 // TocBackend::Item implementation
\r
50 TocBackend::Item::Item(ParConstIterator const & par_it, int d,
\r
51 std::string const & s)
\r
52 : par_it_(par_it), depth_(d), str_(s)
\r
58 size_t pos = s.find(" ");
\r
59 if (pos == string::npos) {
\r
60 // Non labelled item
\r
65 string s2 = s.substr(0, pos);
\r
67 if (s2 == "Chapter" || s2 == "Part") {
\r
68 size_t pos2 = s.find(" ", pos + 1);
\r
69 if (pos2 == string::npos) {
\r
70 // Unnumbered Chapter?? This should not happen.
\r
71 uid_ = s.substr(pos + 1);
\r
75 uid_ = s.substr(pos2 + 1);
\r
79 uid_ = s.substr(pos + 1);
\r
83 bool const TocBackend::Item::isValid() const
\r
85 return depth_ != -1;
\r
89 int const TocBackend::Item::id() const
\r
91 return par_it_->id();
\r
95 int const TocBackend::Item::depth() const
\r
101 std::string const & TocBackend::Item::str() const
\r
107 string const TocBackend::Item::asString() const
\r
109 return string(4 * depth_, ' ') + str_;
\r
113 void TocBackend::Item::goTo(LyXView & lv_) const
\r
115 string const tmp = convert<string>(id());
\r
116 lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));
\r
119 FuncRequest TocBackend::Item::action() const
\r
121 return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id()));
\r
128 ///////////////////////////////////////////////////////////////////////////
\r
129 // TocBackend implementation
\r
131 TocBackend::Toc const & TocBackend::toc(std::string const & type)
\r
133 // Is the type already supported?
\r
134 TocList::const_iterator it = tocs_.find(type);
\r
135 if (it == tocs_.end())
\r
142 bool TocBackend::addType(std::string const & type)
\r
144 // Is the type already supported?
\r
145 TocList::iterator toclist_it = tocs_.find(type);
\r
146 if (toclist_it != tocs_.end())
\r
149 tocs_.insert(make_pair(type, Toc()));
\r
150 types_.push_back(type);
\r
156 void TocBackend::update()
\r
161 BufferParams const & bufparams = buffer_->params();
\r
162 const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();
\r
164 ParConstIterator pit = buffer_->par_iterator_begin();
\r
165 ParConstIterator end = buffer_->par_iterator_end();
\r
166 for (; pit != end; ++pit) {
\r
168 // the string that goes to the toc (could be the optarg)
\r
171 // For each paragraph, traverse its insets and look for
\r
172 // FLOAT_CODE or WRAP_CODE
\r
173 InsetList::const_iterator it = pit->insetlist.begin();
\r
174 InsetList::const_iterator end = pit->insetlist.end();
\r
175 for (; it != end; ++it) {
\r
176 switch (it->inset->lyxCode()) {
\r
177 case InsetBase::FLOAT_CODE:
\r
178 static_cast<InsetFloat*>(it->inset)
\r
179 ->addToToc(tocs_, *buffer_);
\r
181 case InsetBase::WRAP_CODE:
\r
182 static_cast<InsetWrap*>(it->inset)
\r
183 ->addToToc(tocs_, *buffer_);
\r
185 case InsetBase::OPTARG_CODE: {
\r
186 if (!tocstring.empty())
\r
188 Paragraph const & par = *static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();
\r
189 if (!pit->getLabelstring().empty())
\r
190 tocstring = pit->getLabelstring()
\r
192 tocstring += par.asString(*buffer_, false);
\r
200 /// now the toc entry for the paragraph
\r
201 int const toclevel = pit->layout()->toclevel;
\r
202 if (toclevel != LyXLayout::NOT_IN_TOC
\r
203 && toclevel >= min_toclevel
\r
204 && toclevel <= bufparams.tocdepth) {
\r
205 // insert this into the table of contents
\r
206 if (tocstring.empty())
\r
207 tocstring = pit->asString(*buffer_, true);
\r
208 Item const item(pit, toclevel - min_toclevel, tocstring);
\r
209 tocs_["TOC"].push_back(item);
\r
210 //cout << "item inserted str " << item.str()
\r
211 // << " id " << item.id() << endl;
\r
215 TocList::iterator it = tocs_.begin();
\r
216 for (; it != tocs_.end(); ++it)
\r
217 types_.push_back(it->first);
\r
221 TocBackend::TocIterator const TocBackend::item(std::string const & type, ParConstIterator const & par_it)
\r
223 TocList::iterator toclist_it = tocs_.find(type);
\r
224 // Is the type supported?
\r
225 BOOST_ASSERT(toclist_it != tocs_.end());
\r
227 Toc const & toc_vector = toclist_it->second;
\r
228 TocBackend::TocIterator last = toc_vector.begin();
\r
229 TocBackend::TocIterator it = toc_vector.end();
\r
232 for (; it != last; --it) {
\r
234 // A good solution for Items inside insets would be to do:
\r
236 //if (std::distance(it->par_it_, current) <= 0)
\r
239 // But for an unknown reason, std::distance(current, it->par_it_) always
\r
240 // returns a positive value and std::distance(it->par_it_, current) takes forever...
\r
241 // So for now, we do:
\r
242 if (it->par_it_.pit() <= par_it.pit())
\r
246 // We are before the first Toc Item:
\r
251 void TocBackend::asciiTocList(string const & type, ostream & os) const
\r
253 TocList::const_iterator cit = tocs_.find(type);
\r
254 if (cit != tocs_.end()) {
\r
255 Toc::const_iterator ccit = cit->second.begin();
\r
256 Toc::const_iterator end = cit->second.end();
\r
257 for (; ccit != end; ++ccit)
\r
258 os << ccit->asString() << '\n';
\r