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.
15 #include "TocBackend.h"
18 #include "BufferParams.h"
19 #include "FloatList.h"
20 #include "FuncRequest.h"
21 #include "LyXAction.h"
22 #include "Paragraph.h"
25 #include "insets/InsetOptArg.h"
27 #include "support/convert.h"
33 ///////////////////////////////////////////////////////////////////////////
34 // TocItem implementation
36 TocItem::TocItem(ParConstIterator
const & par_it
, int d
,
38 : par_it_(par_it
), depth_(d
), str_(s
)
43 int const TocItem::id() const
49 int const TocItem::depth() const
55 docstring
const & TocItem::str() const
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());
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!"
96 BufferParams
const & bufparams
= buffer_
->params();
97 const int min_toclevel
= bufparams
.getTextClass().min_toclevel();
99 TocIterator toc_item
= item("tableofcontents", par_it
);
103 // For each paragraph, traverse its insets and let them add
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())
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);
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()
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)
146 // For each paragraph, traverse its insets and let them add
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())
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);
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
,
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();
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())
212 if (it
->par_it_
<= par_it_text
)
216 // We are before the first Toc Item:
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';