]> git.lyx.org Git - lyx.git/blob - src/toc.C
we rely on Windows and maybe Linux on a Qt bug
[lyx.git] / src / toc.C
1 /**
2  * \file toc.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 "funcrequest.h"
20 #include "lyxtext.h"
21 #include "LyXAction.h"
22 #include "paragraph.h"
23 #include "pariterator.h"
24 #include "cursor.h"
25 #include "debug.h"
26 #include "undo.h"
27
28
29 namespace lyx {
30 namespace toc {
31
32 void outline(OutlineOp mode,  LCursor & cur)
33 {
34         Buffer * buf = & cur.buffer();
35         pit_type & pit = cur.pit();
36         ParagraphList & pars = buf->text().paragraphs();
37         ParagraphList::iterator bgn = pars.begin();
38         // The first paragraph of the area to be copied:
39         ParagraphList::iterator start = boost::next(bgn, pit);
40         // The final paragraph of area to be copied:
41         ParagraphList::iterator finish = start;
42         ParagraphList::iterator end = pars.end();
43
44         LyXTextClass::const_iterator lit =
45                 buf->params().getLyXTextClass().begin();
46         LyXTextClass::const_iterator const lend =
47                 buf->params().getLyXTextClass().end();
48
49         int const thistoclevel = start->layout()->toclevel;
50         int toclevel;
51         switch (mode) {
52                 case Up: {
53                         // Move out (down) from this section header
54                         if (finish != end)
55                                 ++finish;
56                         // Seek the one (on same level) below
57                         for (; finish != end; ++finish) {
58                                 toclevel = finish->layout()->toclevel;
59                                 if (toclevel != LyXLayout::NOT_IN_TOC
60                                     && toclevel <= thistoclevel) {
61                                         break;
62                                 }
63                         }
64                         ParagraphList::iterator dest = start;
65                         // Move out (up) from this header
66                         if (dest != bgn)
67                                 --dest;
68                         else
69                                 break;
70                         // Search previous same-level header above
71                         for (; dest != bgn; --dest) {
72                                 toclevel = dest->layout()->toclevel;
73                                 if (toclevel != LyXLayout::NOT_IN_TOC
74                                     && toclevel <= thistoclevel) {
75                                         break;
76                                 }
77                         }
78                         // Not found; do nothing
79                         if (dest == bgn)
80                                 break;
81                         pit_type const newpit = std::distance(bgn, dest);
82                         pit_type const len = std::distance(start, finish);
83                         pit += len;
84                         pit = std::min(pit, cur.lastpit());
85                         recordUndo(cur, Undo::ATOMIC, newpit, pit);
86                         pars.insert(dest, start, finish);
87                         start = boost::next(bgn, pit);
88                         pit = newpit;
89                         pars.erase(start, finish);
90                 break;
91                 }
92                 case Down: {
93                         // Go down out of current header:
94                         if (finish != end)
95                                 ++finish;
96                         // Find next same-level header:
97                         for (; finish != end; ++finish) {
98                                 toclevel = finish->layout()->toclevel;
99                                 if (toclevel != LyXLayout::NOT_IN_TOC
100                                     && toclevel <= thistoclevel) {
101                                         break;
102                                 }
103                         }
104                         ParagraphList::iterator dest = finish;
105                         // Go one down from *this* header:
106                         if (dest != end)
107                                 ++dest;
108                         else
109                                 break;
110                         // Go further down to find header to insert in front of:
111                         for (; dest != end; ++dest) {
112                                 toclevel = dest->layout()->toclevel;
113                                 if (toclevel != LyXLayout::NOT_IN_TOC
114                                     && toclevel <= thistoclevel) {
115                                         break;
116                                 }
117                         }
118                         // One such was found:
119                         pit_type newpit = std::distance(bgn, dest);
120                         pit_type const len = std::distance(start, finish);
121                         recordUndo(cur, Undo::ATOMIC, pit, newpit -1);
122                         pars.insert(dest, start, finish);
123                         start = boost::next(bgn, pit);
124                         pit = newpit - len;
125                         pars.erase(start, finish);
126                 break;
127                 }
128                 case In:
129                         recordUndo(cur);
130                         for (; lit != lend; ++lit) {
131                                 if ((*lit)->toclevel == thistoclevel + 1 &&
132                                     start->layout()->labeltype == (*lit)->labeltype) {
133                                         start->layout((*lit));
134                                         break;
135                                 }
136                         }
137                 break;
138                 case Out:
139                         recordUndo(cur);
140                         for (; lit != lend; ++lit) {
141                                 if ((*lit)->toclevel == thistoclevel - 1 &&
142                                     start->layout()->labeltype == (*lit)->labeltype) {
143                                         start->layout((*lit));
144                                         break;
145                                 }
146                         }
147                 break;
148                 default:
149                 break;
150         }
151 }
152
153
154 } // namespace toc
155 } // namespace lyx