Update lyx examples to latest file format (for 1.5.0 release)
[lyx.git] / src / TocBackend.cpp
blob03f3a7433f56de8eabf1e9b61dd52af6a88e2132
1 /**
2 * \file TocBackend.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Jean-Marc Lasgouttes
7 * \author Angus Leeming
8 * \author Abdelrazak Younes
10 * Full author contact details are available in file CREDITS.
13 #include <config.h>
15 #include "TocBackend.h"
17 #include "Buffer.h"
18 #include "BufferParams.h"
19 #include "FloatList.h"
20 #include "FuncRequest.h"
21 #include "LyXAction.h"
22 #include "Paragraph.h"
23 #include "debug.h"
25 #include "insets/InsetOptArg.h"
27 #include "support/convert.h"
29 using std::string;
31 namespace lyx {
33 ///////////////////////////////////////////////////////////////////////////
34 // TocItem implementation
36 TocItem::TocItem(ParConstIterator const & par_it, int d,
37 docstring const & s)
38 : par_it_(par_it), depth_(d), str_(s)
43 int const TocItem::id() const
45 return par_it_->id();
49 int const TocItem::depth() const
51 return depth_;
55 docstring const & TocItem::str() const
57 return str_;
61 docstring const TocItem::asString() const
63 return docstring(4 * depth_, ' ') + str_;
67 FuncRequest TocItem::action() const
69 return FuncRequest(LFUN_PARAGRAPH_GOTO, convert<string>(id()));
73 ///////////////////////////////////////////////////////////////////////////
74 // TocBackend implementation
76 Toc const & TocBackend::toc(std::string const & type) const
78 // Is the type already supported?
79 TocList::const_iterator it = tocs_.find(type);
80 BOOST_ASSERT(it != tocs_.end());
82 return it->second;
86 void TocBackend::updateItem(ParConstIterator const & par_it)
88 if (toc("tableofcontents").empty()) {
89 // FIXME: should not happen,
90 // a call to TocBackend::update() is missing somewhere
91 lyxerr << "TocBackend::updateItem called but the TOC is empty!"
92 << std::endl;
93 return;
96 BufferParams const & bufparams = buffer_->params();
97 const int min_toclevel = bufparams.getTextClass().min_toclevel();
99 TocIterator toc_item = item("tableofcontents", par_it);
101 docstring tocstring;
103 // For each paragraph, traverse its insets and let them add
104 // their toc items
105 InsetList::const_iterator it = toc_item->par_it_->insetlist.begin();
106 InsetList::const_iterator end = toc_item->par_it_->insetlist.end();
107 for (; it != end; ++it) {
108 Inset & inset = *it->inset;
109 if (inset.lyxCode() == Inset::OPTARG_CODE) {
110 if (!tocstring.empty())
111 break;
112 Paragraph const & par =
113 *static_cast<InsetOptArg&>(inset).paragraphs().begin();
114 if (!toc_item->par_it_->getLabelstring().empty())
115 tocstring = toc_item->par_it_->getLabelstring() + ' ';
116 tocstring += par.asString(*buffer_, false);
117 break;
121 int const toclevel = toc_item->par_it_->layout()->toclevel;
122 if (toclevel != Layout::NOT_IN_TOC
123 && toclevel >= min_toclevel
124 && tocstring.empty())
125 tocstring = toc_item->par_it_->asString(*buffer_, true);
127 const_cast<TocItem &>(*toc_item).str_ = tocstring;
131 void TocBackend::update()
133 tocs_.clear();
135 BufferParams const & bufparams = buffer_->params();
136 const int min_toclevel = bufparams.getTextClass().min_toclevel();
138 Toc & toc = tocs_["tableofcontents"];
139 ParConstIterator pit = buffer_->par_iterator_begin();
140 ParConstIterator end = buffer_->par_iterator_end();
141 for (; pit != end; ++pit) {
143 // the string that goes to the toc (could be the optarg)
144 docstring tocstring;
146 // For each paragraph, traverse its insets and let them add
147 // their toc items
148 InsetList::const_iterator it = pit->insetlist.begin();
149 InsetList::const_iterator end = pit->insetlist.end();
150 for (; it != end; ++it) {
151 Inset & inset = *it->inset;
152 inset.addToToc(tocs_, *buffer_, pit);
153 switch (inset.lyxCode()) {
154 case Inset::OPTARG_CODE: {
155 if (!tocstring.empty())
156 break;
157 Paragraph const & par =
158 *static_cast<InsetOptArg&>(inset).paragraphs().begin();
159 if (!pit->getLabelstring().empty())
160 tocstring = pit->getLabelstring() + ' ';
161 tocstring += par.asString(*buffer_, false);
162 break;
164 default:
165 break;
169 /// now the toc entry for the paragraph
170 int const toclevel = pit->layout()->toclevel;
171 if (toclevel != Layout::NOT_IN_TOC
172 && toclevel >= min_toclevel) {
173 // insert this into the table of contents
174 if (tocstring.empty())
175 tocstring = pit->asString(*buffer_, true);
176 toc.push_back(TocItem(pit, toclevel - min_toclevel,
177 tocstring));
183 TocIterator const TocBackend::item(std::string const & type,
184 ParConstIterator const & par_it) const
186 TocList::const_iterator toclist_it = tocs_.find(type);
187 // Is the type supported?
188 BOOST_ASSERT(toclist_it != tocs_.end());
190 Toc const & toc_vector = toclist_it->second;
191 TocIterator last = toc_vector.begin();
192 TocIterator it = toc_vector.end();
193 if (it == last)
194 return it;
196 --it;
198 ParConstIterator par_it_text = par_it;
199 if (par_it_text.inMathed())
200 // It would be better to do
201 // par_it_text.backwardInset();
202 // but this method does not exist.
203 while (par_it_text.inMathed())
204 par_it_text.backwardPos();
206 for (; it != last; --it) {
207 // We verify that we don't compare contents of two
208 // different document. This happens when you
209 // have parent and child documents.
210 if (&it->par_it_[0].inset() != &par_it_text[0].inset())
211 continue;
212 if (it->par_it_ <= par_it_text)
213 return it;
216 // We are before the first Toc Item:
217 return last;
221 void TocBackend::writePlaintextTocList(string const & type, odocstream & os) const
223 TocList::const_iterator cit = tocs_.find(type);
224 if (cit != tocs_.end()) {
225 TocIterator ccit = cit->second.begin();
226 TocIterator end = cit->second.end();
227 for (; ccit != end; ++ccit)
228 os << ccit->asString() << '\n';
233 } // namespace lyx