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 ///////////////////////////////////////////////////////////////////////////
\r
46 // TocBackend::Item implementation
\r
48 TocBackend::Item::Item(ParConstIterator const & par_it, int d,
\r
49 std::string const & s)
\r
50 : par_it_(par_it), depth_(d), str_(s)
\r
56 size_t pos = s.find(" ");
\r
57 if (pos == string::npos) {
\r
58 // Non labelled item
\r
63 string s2 = s.substr(0, pos);
\r
65 if (s2 == "Chapter" || s2 == "Part") {
\r
66 size_t pos2 = s.find(" ", pos + 1);
\r
67 if (pos2 == string::npos) {
\r
68 // Unnumbered Chapter?? This should not happen.
\r
69 uid_ = s.substr(pos + 1);
\r
73 uid_ = s.substr(pos2 + 1);
\r
77 uid_ = s.substr(pos + 1);
\r
81 bool const TocBackend::Item::isValid() const
\r
83 return depth_ != -1;
\r
87 int const TocBackend::Item::id() const
\r
89 return par_it_->id();
\r
93 int const TocBackend::Item::depth() const
\r
99 std::string const & TocBackend::Item::str() const
\r
105 string const TocBackend::Item::asString() const
\r
107 return string(4 * depth_, ' ') + str_;
\r
111 void TocBackend::Item::goTo(LyXView & lv_) const
\r
113 string const tmp = convert<string>(id());
\r
114 lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));
\r
117 FuncRequest TocBackend::Item::action() const
\r
119 return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id()));
\r
126 ///////////////////////////////////////////////////////////////////////////
\r
127 // TocBackend implementation
\r
129 TocBackend::Toc const & TocBackend::toc(std::string const & type)
\r
131 // Is the type already supported?
\r
132 TocList::const_iterator it = tocs_.find(type);
\r
133 if (it == tocs_.end())
\r
140 bool TocBackend::addType(std::string const & type)
\r
142 // Is the type already supported?
\r
143 TocList::iterator toclist_it = tocs_.find(type);
\r
144 if (toclist_it != tocs_.end())
\r
147 tocs_.insert(make_pair(type, Toc()));
\r
148 types_.push_back(type);
\r
154 void TocBackend::update()
\r
159 BufferParams const & bufparams = buffer_->params();
\r
160 const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();
\r
162 ParConstIterator pit = buffer_->par_iterator_begin();
\r
163 ParConstIterator end = buffer_->par_iterator_end();
\r
164 for (; pit != end; ++pit) {
\r
166 // the string that goes to the toc (could be the optarg)
\r
169 // For each paragraph, traverse its insets and look for
\r
170 // FLOAT_CODE or WRAP_CODE
\r
171 InsetList::const_iterator it = pit->insetlist.begin();
\r
172 InsetList::const_iterator end = pit->insetlist.end();
\r
173 for (; it != end; ++it) {
\r
174 switch (it->inset->lyxCode()) {
\r
175 case InsetBase::FLOAT_CODE:
\r
176 static_cast<InsetFloat*>(it->inset)
\r
177 ->addToToc(tocs_, *buffer_);
\r
179 case InsetBase::WRAP_CODE:
\r
180 static_cast<InsetWrap*>(it->inset)
\r
181 ->addToToc(tocs_, *buffer_);
\r
183 case InsetBase::OPTARG_CODE: {
\r
184 if (!tocstring.empty())
\r
186 Paragraph const & par = *static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();
\r
187 if (!pit->getLabelstring().empty())
\r
188 tocstring = pit->getLabelstring()
\r
190 tocstring += par.asString(*buffer_, false);
\r
198 /// now the toc entry for the paragraph
\r
199 int const toclevel = pit->layout()->toclevel;
\r
200 if (toclevel != LyXLayout::NOT_IN_TOC
\r
201 && toclevel >= min_toclevel
\r
202 && toclevel <= bufparams.tocdepth) {
\r
203 // insert this into the table of contents
\r
204 if (tocstring.empty())
\r
205 tocstring = pit->asString(*buffer_, true);
\r
206 Item const item(pit, toclevel - min_toclevel, tocstring);
\r
207 tocs_["TOC"].push_back(item);
\r
208 //cout << "item inserted str " << item.str()
\r
209 // << " id " << item.id() << endl;
\r
213 TocList::iterator it = tocs_.begin();
\r
214 for (; it != tocs_.end(); ++it)
\r
215 types_.push_back(it->first);
\r
219 TocBackend::TocIterator const TocBackend::item(std::string const & type, ParConstIterator const & par_it)
\r
221 TocList::iterator toclist_it = tocs_.find(type);
\r
222 // Is the type supported?
\r
223 BOOST_ASSERT(toclist_it != tocs_.end());
\r
225 Toc const & toc_vector = toclist_it->second;
\r
226 TocBackend::TocIterator last = toc_vector.begin();
\r
227 TocBackend::TocIterator it = toc_vector.end();
\r
230 for (; it != last; --it) {
\r
232 // A good solution for Items inside insets would be to do:
\r
234 //if (std::distance(it->par_it_, current) <= 0)
\r
237 // But for an unknown reason, std::distance(current, it->par_it_) always
\r
238 // returns a positive value and std::distance(it->par_it_, current) takes forever...
\r
239 // So for now, we do:
\r
240 if (it->par_it_.pit() <= par_it.pit())
\r
244 // We are before the first Toc Item:
\r
249 void TocBackend::asciiTocList(string const & type, ostream & os) const
\r
251 TocList::const_iterator cit = tocs_.find(type);
\r
252 if (cit != tocs_.end()) {
\r
253 Toc::const_iterator ccit = cit->second.begin();
\r
254 Toc::const_iterator end = cit->second.end();
\r
255 for (; ccit != end; ++ccit)
\r
256 os << ccit->asString() << '\n';
\r