]> git.lyx.org Git - lyx.git/blob - src/TocBackend.C
Rev. 13714 has a wrong fix, I just erased empty_toc_ and replaced that with an BOOST_...
[lyx.git] / src / TocBackend.C
1 /**\r
2  * \file TocBackend.C\r
3  * This file is part of LyX, the document processor.\r
4  * Licence details can be found in the file COPYING.\r
5  *\r
6  * \author Jean-Marc Lasgouttes\r
7  * \author Angus Leeming\r
8  * \author Abdelrazak Younes\r
9  *\r
10  * Full author contact details are available in file CREDITS.\r
11  */\r
12 \r
13 #include <config.h>\r
14 \r
15 #include "toc.h"\r
16 \r
17 #include "buffer.h"\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
23 #include "cursor.h"\r
24 #include "debug.h"\r
25 \r
26 #include "frontends/LyXView.h"\r
27 \r
28 #include "insets/insetfloat.h"\r
29 #include "insets/insetoptarg.h"\r
30 #include "insets/insetwrap.h"\r
31 \r
32 #include "support/convert.h"\r
33 \r
34 #include <iostream>\r
35 \r
36 using std::vector;\r
37 using std::max;\r
38 using std::ostream;\r
39 using std::string;\r
40 using std::cout;\r
41 using std::endl;\r
42 \r
43 namespace lyx {\r
44 \r
45 ///////////////////////////////////////////////////////////////////////////\r
46 // TocBackend::Item implementation\r
47 \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
51 {\r
52 /*\r
53         if (!uid_.empty())\r
54                 return;\r
55 \r
56         size_t pos = s.find(" ");\r
57         if (pos == string::npos) {\r
58                 // Non labelled item\r
59                 uid_ = s;\r
60                 return;\r
61         }\r
62 \r
63         string s2 = s.substr(0, pos);\r
64 \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
70                         return;\r
71                 }\r
72                 // Chapter or Part\r
73                 uid_ = s.substr(pos2 + 1);\r
74                 return;\r
75         }\r
76         // Numbered Item.\r
77         uid_ = s.substr(pos + 1);\r
78         */\r
79 }\r
80 \r
81 bool const TocBackend::Item::isValid() const\r
82 {\r
83         return depth_ != -1;\r
84 }\r
85 \r
86 \r
87 int const TocBackend::Item::id() const\r
88 {\r
89         return par_it_->id();\r
90 }\r
91 \r
92 \r
93 int const TocBackend::Item::depth() const\r
94 {\r
95         return depth_;\r
96 }\r
97 \r
98 \r
99 std::string const & TocBackend::Item::str() const\r
100 {\r
101         return str_;\r
102 }\r
103 \r
104 \r
105 string const TocBackend::Item::asString() const\r
106 {\r
107         return string(4 * depth_, ' ') + str_;\r
108 }\r
109 \r
110 \r
111 void TocBackend::Item::goTo(LyXView & lv_) const\r
112 {\r
113         string const tmp = convert<string>(id());\r
114         lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));\r
115 }\r
116 \r
117 FuncRequest TocBackend::Item::action() const\r
118 {\r
119         return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id()));\r
120 }\r
121 \r
122 \r
123 \r
124 \r
125 \r
126 ///////////////////////////////////////////////////////////////////////////\r
127 // TocBackend implementation\r
128 \r
129 TocBackend::Toc const & TocBackend::toc(std::string const & type)\r
130 {\r
131         // Is the type already supported?\r
132         TocList::const_iterator it = tocs_.find(type);\r
133         BOOST_ASSERT(it != tocs_.end());\r
134 \r
135         return it->second;\r
136 }\r
137 \r
138 \r
139 bool TocBackend::addType(std::string const & type)\r
140 {\r
141         // Is the type already supported?\r
142         TocList::iterator toclist_it = tocs_.find(type);\r
143         if (toclist_it != tocs_.end())\r
144                 return false;\r
145 \r
146         tocs_.insert(make_pair(type, Toc()));\r
147         types_.push_back(type);\r
148 \r
149         return true;\r
150 }\r
151 \r
152 \r
153 void TocBackend::update()\r
154 {\r
155         tocs_.clear();\r
156         types_.clear();\r
157 \r
158         BufferParams const & bufparams = buffer_->params();\r
159         const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();\r
160 \r
161         ParConstIterator pit = buffer_->par_iterator_begin();\r
162         ParConstIterator end = buffer_->par_iterator_end();\r
163         for (; pit != end; ++pit) {\r
164 \r
165                 // the string that goes to the toc (could be the optarg)\r
166                 string tocstring;\r
167 \r
168                 // For each paragraph, traverse its insets and look for\r
169                 // FLOAT_CODE or WRAP_CODE\r
170                 InsetList::const_iterator it = pit->insetlist.begin();\r
171                 InsetList::const_iterator end = pit->insetlist.end();\r
172                 for (; it != end; ++it) {\r
173                         switch (it->inset->lyxCode()) {\r
174                         case InsetBase::FLOAT_CODE:\r
175                                 static_cast<InsetFloat*>(it->inset)\r
176                                         ->addToToc(tocs_, *buffer_);\r
177                                 break;\r
178                         case InsetBase::WRAP_CODE:\r
179                                 static_cast<InsetWrap*>(it->inset)\r
180                                         ->addToToc(tocs_, *buffer_);\r
181                                 break;\r
182                         case InsetBase::OPTARG_CODE: {\r
183                                 if (!tocstring.empty())\r
184                                         break;\r
185                                 Paragraph const & par = *static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();\r
186                                 if (!pit->getLabelstring().empty())\r
187                                         tocstring = pit->getLabelstring()\r
188                                                 + ' ';\r
189                                 tocstring += par.asString(*buffer_, false);\r
190                                 break;\r
191                         }\r
192                         default:\r
193                                 break;\r
194                         }\r
195                 }\r
196 \r
197                 /// now the toc entry for the paragraph\r
198                 int const toclevel = pit->layout()->toclevel;\r
199                 if (toclevel != LyXLayout::NOT_IN_TOC\r
200                     && toclevel >= min_toclevel\r
201                     && toclevel <= bufparams.tocdepth) {\r
202                         // insert this into the table of contents\r
203                         if (tocstring.empty())\r
204                                 tocstring = pit->asString(*buffer_, true);\r
205                         Item const item(pit, toclevel - min_toclevel, tocstring);\r
206                         tocs_["TOC"].push_back(item);\r
207                         //cout << "item inserted str " << item.str()\r
208                         //      << "  id " << item.id() << endl;\r
209                 }\r
210         }\r
211 \r
212         TocList::iterator it = tocs_.begin();\r
213         for (; it != tocs_.end(); ++it)\r
214                 types_.push_back(it->first);\r
215 }\r
216 \r
217 \r
218 TocBackend::TocIterator const TocBackend::item(std::string const & type, ParConstIterator const & par_it)\r
219 {\r
220         TocList::iterator toclist_it = tocs_.find(type);\r
221         // Is the type supported?\r
222         BOOST_ASSERT(toclist_it != tocs_.end());\r
223 \r
224         Toc const & toc_vector = toclist_it->second;\r
225         TocBackend::TocIterator last = toc_vector.begin();\r
226         TocBackend::TocIterator it = toc_vector.end();\r
227         --it;\r
228 \r
229         for (; it != last; --it) {\r
230                 \r
231                 // A good solution for Items inside insets would be to do:\r
232                 //\r
233                 //if (std::distance(it->par_it_, current) <= 0)\r
234                 //      return it;\r
235                 //\r
236                 // But for an unknown reason, std::distance(current, it->par_it_) always\r
237                 // returns  a positive value and std::distance(it->par_it_, current) takes forever...\r
238                 // So for now, we do:\r
239                 if (it->par_it_.pit() <= par_it.pit())\r
240                         return it;\r
241         }\r
242 \r
243         // We are before the first Toc Item:\r
244         return last;\r
245 }\r
246 \r
247 \r
248 void TocBackend::asciiTocList(string const & type, ostream & os) const\r
249 {\r
250         TocList::const_iterator cit = tocs_.find(type);\r
251         if (cit != tocs_.end()) {\r
252                 Toc::const_iterator ccit = cit->second.begin();\r
253                 Toc::const_iterator end = cit->second.end();\r
254                 for (; ccit != end; ++ccit)\r
255                         os << ccit->asString() << '\n';\r
256         }\r
257 }\r
258 \r
259 \r
260 } // namespace lyx\r