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